#pragma once
#include "sdkconfig.h"

#ifndef CONFIG_IDF_TARGET_ESP32
#include <lvgl.h>
#include <thread>
#include <memory>
#include <vector>

#include <freertos/FreeRTOS.h>
#include <freertos/queue.h>
#include <freertos/semphr.h>

#include "camera.h"
#include "jpg/image_to_jpeg.h"
#include "esp_video_init.h"

struct JpegChunk {
    uint8_t* data;
    size_t len;
};

class Esp32Camera : public Camera {
public:
    // [T04] 人脸检测用帧引用：zero-copy 指向 mmap 缓冲区
    // 使用者获得后必须在短时间内调用 ReleaseDetectionFrame 归还，否则 V4L2 流会卡死
    struct FrameRef {
        const uint8_t* data = nullptr;
        size_t len = 0;
        uint16_t width = 0;
        uint16_t height = 0;
        v4l2_pix_fmt_t format = 0;
        uint32_t buf_index = 0;  // 用于 VIDIOC_QBUF 归还
    };

private:
    struct FrameBuffer {
        uint8_t *data = nullptr;
        size_t len = 0;
        uint16_t width = 0;
        uint16_t height = 0;
        v4l2_pix_fmt_t format = 0;
    } frame_;
    v4l2_pix_fmt_t sensor_format_ = 0;
#ifdef CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE
    uint16_t sensor_width_ = 0;
    uint16_t sensor_height_ = 0;
#endif  // CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE
    int video_fd_ = -1;
    bool streaming_on_ = false;
    struct MmapBuffer { void *start = nullptr; size_t length = 0; };
    std::vector<MmapBuffer> mmap_buffers_;
    std::string explain_url_;
    std::string explain_token_;
    std::thread encoder_thread_;

    // [T04] 采集互斥锁：face_track 和 MCP 拍照共享 V4L2 DQBUF 单槽
    // 使用 FreeRTOS 信号量（非 std::mutex）以获得 timeout 语义
    SemaphoreHandle_t capture_mutex_ = nullptr;

public:
    Esp32Camera(const esp_video_init_config_t& config);
    ~Esp32Camera();

    virtual void SetExplainUrl(const std::string& url, const std::string& token);
    virtual bool Capture();
    // 翻转控制函数
    virtual bool SetHMirror(bool enabled) override;
    virtual bool SetVFlip(bool enabled) override;
    virtual std::string Explain(const std::string& question);

    // [T01] 最小化 V4L2 DQBUF/QBUF 探测方法
    // 用途：验证 OV3660 + esp_video 底层采集链路是否正常工作
    // 不做 JPEG 编码、不做 PSRAM 大分配、不触发 encoder_thread
    // 调用链路：VIDIOC_DQBUF → 立即 VIDIOC_QBUF 归还
    // @param elapsed_us 输出参数，返回两次 ioctl 间的耗时（微秒）
    // @return 成功返回 true；streaming 未启动或 ioctl 失败返回 false
    bool ProbeFrameCapture(int64_t* elapsed_us);

    // [T04] 人脸检测用帧采集：超短 timeout（10ms）拿不到锁则跳帧
    // 语义：人脸检测允许丢帧，拍照不允许丢
    // 成功返回 true 后，out 指向的缓冲有效期到 ReleaseDetectionFrame 为止
    // 必须配对调用：Capture 成功 → Release 归还（否则 V4L2 队列耗尽）
    bool CaptureForDetection(FrameRef* out);

    // [T04] 归还人脸检测帧：配对 CaptureForDetection
    // 内部执行 VIDIOC_QBUF 将缓冲归还给 V4L2 驱动，并释放 capture_mutex_
    bool ReleaseDetectionFrame(const FrameRef& ref);
};

#endif // ndef CONFIG_IDF_TARGET_ESP32