/**
 * @file webp_decoder.hpp
 * @brief SIMD-accelerated WebP decoder using libwebp
 *
 * Features:
 * - SIMD acceleration (SSE2, SSE4.1, AVX2, NEON)
 * - Modern format with better compression than JPEG
 * - Lossless and lossy compression support
 * - Direct RGB output
 * - Zero-copy memory-mapped input
 * - Pooled output buffers
 * - Thread-safe (one instance per thread)
 *
 * WebP provides 25-35% better compression than JPEG at same quality.
 * Widely supported in Chrome, Firefox, Edge, Safari 14+.
 */

#pragma once

#ifdef HAVE_WEBP

#include "../core/sample.hpp"
#include "../core/buffer_pool.hpp"
#include "../core/compat.hpp"  // span polyfill for C++17
#include <webp/decode.h>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <stdexcept>
#include <string>
#include <vector>

namespace turboloader {

/**
 * @brief High-performance SIMD-accelerated WebP decoder
 *
 * libwebp provides SIMD optimizations:
 * - SSE2 on x86/x64 (baseline)
 * - SSE4.1 for advanced operations
 * - AVX2 on modern Intel/AMD CPUs
 * - NEON on ARM processors
 *
 * Performance:
 * - 1.5-3x faster than software-only decode
 * - Comparable to libjpeg-turbo for lossy WebP
 * - Excellent for lossless WebP
 *
 * Thread-safe when each thread has its own instance.
 */
class WebPDecoder {
public:
    /**
     * @brief Construct decoder with optional buffer pool
     */
    explicit WebPDecoder(BufferPool* pool = nullptr)
        : buffer_pool_(pool) {}

    /**
     * @brief Decode WebP data to RGB
     *
     * @param webp_data Span of compressed WebP bytes
     * @param output Output buffer for RGB data (resized automatically)
     * @param width Output: image width
     * @param height Output: image height
     * @param channels Output: number of channels (always 3 for RGB)
     *
     * @throws std::runtime_error on decode failure
     *
     * Uses SIMD-accelerated decoding path when available.
     */
    void decode(
        std::span<const uint8_t> webp_data,
        std::vector<uint8_t>& output,
        int& width,
        int& height,
        int& channels
    ) {
        if (webp_data.empty()) {
            throw std::runtime_error("Empty WebP data");
        }

        // Get dimensions (fast header parse)
        if (!WebPGetInfo(webp_data.data(), webp_data.size(), &width, &height)) {
            throw std::runtime_error("Failed to get WebP info");
        }

        channels = 3;  // RGB

        // Allocate output buffer
        size_t total_size = width * height * channels;
        output.resize(total_size);

        // Decode to RGB (SIMD-accelerated in libwebp)
        // This uses SSE2/AVX2/NEON depending on CPU
        if (!WebPDecodeRGBInto(webp_data.data(), webp_data.size(),
                               output.data(), output.size(), width * channels)) {
            throw std::runtime_error("WebP decode error");
        }
    }

    /**
     * @brief Decode WebP into Sample with pooled buffer
     */
    void decode_sample(Sample& sample) {
        if (sample.jpeg_data.empty()) {
            throw std::runtime_error("Sample has no image data");
        }

        // Get pooled buffer if available
        std::vector<uint8_t> buffer;
        if (buffer_pool_) {
            auto pooled = buffer_pool_->acquire();
            buffer = std::move(*pooled);
        }

        // Decode WebP
        decode(sample.jpeg_data, buffer, sample.width, sample.height, sample.channels);

        // Move buffer into sample
        sample.decoded_rgb = std::move(buffer);
    }

    /**
     * @brief Get decoder info with SIMD capabilities
     */
    static std::string version_info() {
        int version = WebPGetDecoderVersion();
        int major = (version >> 16) & 0xFF;
        int minor = (version >> 8) & 0xFF;
        int revision = version & 0xFF;

        return "libwebp " + std::to_string(major) + "." +
               std::to_string(minor) + "." + std::to_string(revision) +
               " (SIMD: SSE2/AVX2/NEON)";
    }

private:
    BufferPool* buffer_pool_;
};

} // namespace turboloader

#endif // HAVE_WEBP
