/**
 * @file camera.cpp
 * @brief GC2083 摄像头驱动实现 - 基于全志 MPP 框架
 * 
 * 架构: VI (Video Input) → ISP → VENC (JPEG Encoder)
 * 模式: 绑定模式 (自动流转，高性能)
 */

#include "camera.h"
#include <cstring>
#include <ctime>
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>

extern "C" {
#include <mpi_sys.h>
#include <mm_common.h>
#include <mpi_videoformat_conversion.h>
}

// 日志宏
#define LOG_TAG "Camera"
#define LOGD(fmt, ...) printf("[%s][D] " fmt "\n", LOG_TAG, ##__VA_ARGS__)
#define LOGI(fmt, ...) printf("[%s][I] " fmt "\n", LOG_TAG, ##__VA_ARGS__)
#define LOGW(fmt, ...) printf("[%s][W] " fmt "\n", LOG_TAG, ##__VA_ARGS__)
#define LOGE(fmt, ...) printf("[%s][E] " fmt "\n", LOG_TAG, ##__VA_ARGS__)

// 默认配置 (Day 13: 降低负载减少网络拥堵)
#define DEFAULT_WIDTH       640   // Day 13: 从1280降低到640
#define DEFAULT_HEIGHT      480   // Day 13: 从720降低到480
// Day 22 优化: 户外稳定模式，适应4G手机热点网络波动
#define DEFAULT_FPS         8     // 8fps 平衡流畅与带宽
#define DEFAULT_QUALITY     45    // Qfactor=45，适度压缩节省带宽
#define VI_BUFFER_NUM       5     // 增加缓冲区数量避免溢出 (Day 11)
#define VBV_BUFFER_SIZE     2048  // Day 13: 降低到2MB，640x480不需要4MB

// GC2083 配置
#define VIPP_DEV_ID         0   // sensor0 (GC2083)
#define ISP_DEV_ID          0
#define VI_CHN_ID           0
#define VENC_CHN_START      0

Camera::Camera()
    : m_vi_dev(VIPP_DEV_ID)
    , m_vi_chn(VI_CHN_ID)
    , m_isp_dev(ISP_DEV_ID)
    , m_venc_chn(MM_INVALID_CHN)
    , m_width(DEFAULT_WIDTH)
    , m_height(DEFAULT_HEIGHT)
    , m_quality(DEFAULT_QUALITY)
    , m_fps(0.0f)
    , m_frame_count(0)
    , m_last_time(0)
{
    LOGD("Camera constructor");
}

Camera::~Camera()
{
    LOGD("Camera destructor");
    
    // 停止编码器
    if (m_venc_chn != MM_INVALID_CHN) {
        AW_MPI_VENC_StopRecvPic(m_venc_chn);
        AW_MPI_VENC_DestroyChn(m_venc_chn);
    }
    
    // 停止 VI
    AW_MPI_VI_DisableVirChn(m_vi_dev, m_vi_chn);
    AW_MPI_VI_DestroyVirChn(m_vi_dev, m_vi_chn);
    AW_MPI_VI_DisableVipp(m_vi_dev);
    
    // 停止 ISP
    AW_MPI_ISP_Stop(m_isp_dev);
    AW_MPI_VI_DestroyVipp(m_vi_dev);
    
    // 退出系统
    AW_MPI_SYS_Exit();
}

void Camera::deinit()
{
    LOGI("[Camera] Deinitializing for recovery...");
    
    // 停止编码器
    if (m_venc_chn != MM_INVALID_CHN) {
        AW_MPI_VENC_StopRecvPic(m_venc_chn);
        AW_MPI_VENC_DestroyChn(m_venc_chn);
        m_venc_chn = MM_INVALID_CHN;
    }
    
    // 停止 VI
    AW_MPI_VI_DisableVirChn(m_vi_dev, m_vi_chn);
    AW_MPI_VI_DestroyVirChn(m_vi_dev, m_vi_chn);
    AW_MPI_VI_DisableVipp(m_vi_dev);
    
    // 停止 ISP
    AW_MPI_ISP_Stop(m_isp_dev);
    AW_MPI_VI_DestroyVipp(m_vi_dev);
    
    // 退出系统
    AW_MPI_SYS_Exit();
    
    // 重置统计
    m_fps = 0.0f;
    m_frame_count = 0;
    m_last_time = 0;
    
    LOGI("[Camera] Deinitialized, ready for reinit");
}

bool Camera::init()
{
    LOGI("Initializing camera: %dx%d @%dfps", m_width, m_height, DEFAULT_FPS);
    
    // 1. 初始化 MPP 系统
    MPP_SYS_CONF_S sys_conf;
    memset(&sys_conf, 0, sizeof(MPP_SYS_CONF_S));
    sys_conf.nAlignWidth = 32;
    AW_MPI_SYS_SetConf(&sys_conf);
    
    if (AW_MPI_SYS_Init() != SUCCESS) {
        LOGE("AW_MPI_SYS_Init failed");
        return false;
    }
    LOGD("MPP system initialized");
    
    // 2. 创建 VI 设备 (初始化 sensor subdev)
    LOGD("Creating VI device %d...", m_vi_dev);
    ERRORTYPE ret = AW_MPI_VI_CreateVipp(m_vi_dev);
    if (ret != SUCCESS) {
        LOGE("AW_MPI_VI_CreateVipp failed: 0x%x", ret);
        AW_MPI_SYS_Exit();
        return false;
    }
    LOGD("VI device %d created successfully", m_vi_dev);
    
    // 配置 VIPP 属性 (使用 LBC 2.5x 压缩)
    LOGD("Configuring VI attributes: %dx%d @%dfps", m_width, m_height, DEFAULT_FPS);
    VI_ATTR_S vi_attr;
    memset(&vi_attr, 0, sizeof(VI_ATTR_S));
    vi_attr.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    vi_attr.memtype = V4L2_MEMORY_MMAP;
    vi_attr.format.pixelformat = map_PIXEL_FORMAT_E_to_V4L2_PIX_FMT(MM_PIXEL_FORMAT_YUV_AW_LBC_2_5X);
    vi_attr.format.field = V4L2_FIELD_NONE;
    vi_attr.format.colorspace = V4L2_COLORSPACE_REC709;
    vi_attr.format.width = m_width;
    vi_attr.format.height = m_height;
    vi_attr.nbufs = VI_BUFFER_NUM;
    vi_attr.nplanes = 2;
    vi_attr.fps = DEFAULT_FPS;
    vi_attr.use_current_win = 0;
    vi_attr.wdr_mode = 0;
    vi_attr.capturemode = V4L2_MODE_VIDEO;
    vi_attr.drop_frame_num = 0;
    
    if (AW_MPI_VI_SetVippAttr(m_vi_dev, &vi_attr) != SUCCESS) {
        LOGE("AW_MPI_VI_SetVippAttr failed");
        return false;
    }
    LOGD("VI device created and configured");
    
    // 3. 启动 ISP (连接到 sensor)
    if (!init_isp()) {
        LOGE("init_isp failed");
        return false;
    }
    
    // 4. 创建 VI 通道并启用
    if (AW_MPI_VI_CreateVirChn(m_vi_dev, m_vi_chn, NULL) != SUCCESS) {
        LOGE("AW_MPI_VI_CreateVirChn failed");
        return false;
    }
    
    if (AW_MPI_VI_EnableVipp(m_vi_dev) != SUCCESS) {
        LOGE("AW_MPI_VI_EnableVipp failed");
        return false;
    }
    LOGD("VI channel created and enabled");
    
    // 5. 初始化 VENC (Video Encoder)
    if (!init_venc()) {
        LOGE("init_venc failed");
        return false;
    }
    
    // 6. 绑定 VI → VENC
    MPP_CHN_S vi_chn = {MOD_ID_VIU, m_vi_dev, m_vi_chn};
    MPP_CHN_S venc_chn = {MOD_ID_VENC, 0, m_venc_chn};
    if (AW_MPI_SYS_Bind(&vi_chn, &venc_chn) != SUCCESS) {
        LOGE("AW_MPI_SYS_Bind failed");
        return false;
    }
    LOGD("VI-VENC bind successful");
    
    // 7. 启动采集和编码
    if (AW_MPI_VI_EnableVirChn(m_vi_dev, m_vi_chn) != SUCCESS) {
        LOGE("AW_MPI_VI_EnableVirChn failed");
        return false;
    }
    
    if (AW_MPI_VENC_StartRecvPic(m_venc_chn) != SUCCESS) {
        LOGE("AW_MPI_VENC_StartRecvPic failed");
        return false;
    }
    
    LOGI("Camera initialized successfully");
    return true;
}

bool Camera::init_vi()
{
    // VI 初始化已在 init() 中完成
    return true;
}

bool Camera::init_isp()
{
    LOGD("Initializing ISP...");
    
    // 启动 ISP
    if (AW_MPI_ISP_Run(m_isp_dev) != SUCCESS) {
        LOGE("AW_MPI_ISP_Run failed");
        return false;
    }
    
    LOGD("ISP running");
    return true;
}

bool Camera::init_venc()
{
    LOGD("Initializing VENC (JPEG)...");
    
    // 使用固定的大VBV缓冲区 (4MB) 避免 VBV FULL 错误
    unsigned int vbv_buf_size = VBV_BUFFER_SIZE * 1024;  // 4MB
    unsigned int vbv_thresh_size = m_width * m_height;
    
    LOGD("VBV buffer size: %u KB (%u bytes)", VBV_BUFFER_SIZE, vbv_buf_size);
    
    // 配置 VENC 通道属性
    VENC_CHN_ATTR_S venc_attr;
    memset(&venc_attr, 0, sizeof(VENC_CHN_ATTR_S));
    
    venc_attr.VeAttr.Type = PT_JPEG;
    venc_attr.VeAttr.mVippID = m_vi_dev;
    venc_attr.VeAttr.MaxKeyInterval = 1;
    venc_attr.VeAttr.SrcPicWidth = m_width;
    venc_attr.VeAttr.SrcPicHeight = m_height;
    venc_attr.VeAttr.Field = VIDEO_FIELD_FRAME;
    venc_attr.VeAttr.PixelFormat = MM_PIXEL_FORMAT_YUV_AW_LBC_2_5X;
    venc_attr.VeAttr.mColorSpace = V4L2_COLORSPACE_REC709;
    venc_attr.VeAttr.Rotate = ROTATE_NONE;
    
    // JPEG 特定配置
    venc_attr.VeAttr.AttrJpeg.MaxPicWidth = 0;
    venc_attr.VeAttr.AttrJpeg.MaxPicHeight = 0;
    venc_attr.VeAttr.AttrJpeg.BufSize = vbv_buf_size;
    venc_attr.VeAttr.AttrJpeg.mThreshSize = vbv_thresh_size;
    venc_attr.VeAttr.AttrJpeg.bByFrame = TRUE;
    venc_attr.VeAttr.AttrJpeg.PicWidth = m_width;
    venc_attr.VeAttr.AttrJpeg.PicHeight = m_height;
    venc_attr.VeAttr.AttrJpeg.bSupportDCF = FALSE;
    
    // 创建编码通道
    m_venc_chn = VENC_CHN_START;
    bool success = false;
    while (m_venc_chn < VENC_MAX_CHN_NUM) {
        ERRORTYPE ret = AW_MPI_VENC_CreateChn(m_venc_chn, &venc_attr);
        if (ret == SUCCESS) {
            success = true;
            break;
        } else if (ret == ERR_VENC_EXIST) {
            m_venc_chn++;
        } else {
            LOGE("AW_MPI_VENC_CreateChn failed: 0x%x", ret);
            m_venc_chn++;
        }
    }
    
    if (!success) {
        LOGE("Failed to create VENC channel");
        m_venc_chn = MM_INVALID_CHN;
        return false;
    }
    
    // 设置 JPEG 质量
    VENC_PARAM_JPEG_S jpeg_param;
    memset(&jpeg_param, 0, sizeof(VENC_PARAM_JPEG_S));
    jpeg_param.Qfactor = m_quality;
    AW_MPI_VENC_SetJpegParam(m_venc_chn, &jpeg_param);
    
    // 允许丢帧以防止VBV满时完全阻塞 (Day 11: 改为允许丢帧)
    AW_MPI_VENC_ForbidDiscardingFrame(m_venc_chn, FALSE);
    
    LOGD("VENC initialized: channel=%d, VBV=%uKB, quality=%d", 
         m_venc_chn, vbv_buf_size/1024, m_quality);
    return true;
}

bool Camera::capture_frame(uint8_t** jpeg_data, size_t* jpeg_size)
{
    if (!jpeg_data || !jpeg_size) {
        LOGE("Invalid parameters");
        return false;
    }
    
    // 获取编码流
    VENC_STREAM_S stream;
    VENC_PACK_S pack;
    memset(&stream, 0, sizeof(VENC_STREAM_S));
    memset(&pack, 0, sizeof(VENC_PACK_S));
    stream.mpPack = &pack;
    stream.mPackCount = 1;
    
    // 增加超时时间到10秒，并添加重试机制
    const int max_retries = 3;
    const int timeout_ms = 10000;  // 10秒超时
    ERRORTYPE ret = ERR_VENC_BUF_EMPTY;
    
    for (int retry = 0; retry < max_retries && ret != SUCCESS; retry++) {
        if (retry > 0) {
            LOGW("Retry %d/%d getting stream...", retry, max_retries);
            usleep(100000);  // 100ms延迟再重试
        }
        ret = AW_MPI_VENC_GetStream(m_venc_chn, &stream, timeout_ms);
    }
    
    if (ret != SUCCESS) {
        LOGE("AW_MPI_VENC_GetStream failed after %d retries: 0x%x", max_retries, ret);
        return false;
    }
    
    // 计算总大小
    size_t total_size = stream.mpPack[0].mLen0 + stream.mpPack[0].mLen1 + stream.mpPack[0].mLen2;
    if (total_size == 0) {
        LOGE("Empty JPEG frame");
        AW_MPI_VENC_ReleaseStream(m_venc_chn, &stream);
        return false;
    }
    
    // 分配内存并拷贝数据
    uint8_t* buffer = new uint8_t[total_size];
    size_t offset = 0;
    
    if (stream.mpPack[0].mLen0 > 0 && stream.mpPack[0].mpAddr0) {
        memcpy(buffer + offset, stream.mpPack[0].mpAddr0, stream.mpPack[0].mLen0);
        offset += stream.mpPack[0].mLen0;
    }
    if (stream.mpPack[0].mLen1 > 0 && stream.mpPack[0].mpAddr1) {
        memcpy(buffer + offset, stream.mpPack[0].mpAddr1, stream.mpPack[0].mLen1);
        offset += stream.mpPack[0].mLen1;
    }
    if (stream.mpPack[0].mLen2 > 0 && stream.mpPack[0].mpAddr2) {
        memcpy(buffer + offset, stream.mpPack[0].mpAddr2, stream.mpPack[0].mLen2);
        offset += stream.mpPack[0].mLen2;
    }
    
    // 释放流
    AW_MPI_VENC_ReleaseStream(m_venc_chn, &stream);
    
    // 更新 FPS 统计
    update_fps_stats();
    
    // 返回结果
    *jpeg_data = buffer;
    *jpeg_size = total_size;
    
    LOGD("Captured JPEG: %zu bytes, FPS: %.1f", total_size, m_fps);
    return true;
}

void Camera::release_frame(uint8_t* jpeg_data)
{
    if (jpeg_data) {
        delete[] jpeg_data;
    }
}

bool Camera::set_framesize(const std::string& size)
{
    LOGW("set_framesize not implemented yet: %s", size.c_str());
    // TODO: 动态调整分辨率需要重新配置 VI 和 VENC
    return false;
}

void Camera::set_quality(int quality)
{
    if (quality < 1 || quality > 99) {
        LOGW("Invalid quality %d, using default %d", quality, DEFAULT_QUALITY);
        quality = DEFAULT_QUALITY;
    }
    
    m_quality = quality;
    
    if (m_venc_chn != MM_INVALID_CHN) {
        VENC_PARAM_JPEG_S jpeg_param;
        memset(&jpeg_param, 0, sizeof(VENC_PARAM_JPEG_S));
        jpeg_param.Qfactor = m_quality;
        AW_MPI_VENC_SetJpegParam(m_venc_chn, &jpeg_param);
        LOGD("JPEG quality updated: %d", m_quality);
    }
}

void Camera::update_fps_stats()
{
    m_frame_count++;
    
    struct timeval tv;
    gettimeofday(&tv, NULL);
    uint64_t current_time = tv.tv_sec * 1000000ULL + tv.tv_usec;
    
    if (m_last_time == 0) {
        m_last_time = current_time;
        return;
    }
    
    uint64_t elapsed = current_time - m_last_time;
    if (elapsed >= 1000000) {  // 1秒
        m_fps = (float)m_frame_count * 1000000.0f / elapsed;
        m_frame_count = 0;
        m_last_time = current_time;
    }
}
