#include "common.h"

static const char *filePrefix = NULL;
static int fileNum = 0;
static const char *target_ip = NULL;
static const char *dataType = NULL;
static int target_port = 0;

// 初始化网络
int init_udp_network(const char *target_ip, int target_port, struct sockaddr_in *dest_addr)
{
    // 创建UDP套接字
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        printf("创建套接字失败\n");
        return -1;
    }

    // 设置目标地址
    memset(dest_addr, 0, sizeof(struct sockaddr_in));
    dest_addr->sin_family = AF_INET;
    dest_addr->sin_port = htons(target_port);
    if (inet_pton(AF_INET, target_ip, &(dest_addr->sin_addr)) <= 0) {
        printf("无效的目标IP地址\n");
        close(sockfd);
        return -1;
    }

    return sockfd;
}

// 解析帧大小
int parse_frame_size(dataType_e dataType, int width, int height, int filesize)
{
    int frame_size = 0;
    switch (dataType)
    {
    case GRAPH_JPG:
        frame_size = filesize;
        break;
    case GRAPH_RGB565:
    case GRAPH_RGB555:
        frame_size = width * height * sizeof(uint16_t);
        break;
    case GRAPH_GRAY8:
        frame_size = width * height * sizeof(uint8_t);
        break;
    default:
        printf("%s %s 不支持的帧类型\n", __FUNCTION__, __LINE__);
        break;
    }
    return frame_size;
}

int send_buffer(int sockfd, struct sockaddr_in *dest_addr, uint8_t *data, int size)
{
    // 分块发送文件
    uint8_t chunk[CHUNK_SIZE];
    int current_chunk = 0;
    int offset = 0;
    int copySize = 0;
    ssize_t total_sent = 0;

    while (offset < size) {
        // 分块发送避免包太大
        memset(chunk, 0, CHUNK_SIZE);
        if (offset + CHUNK_SIZE < size)
            copySize = CHUNK_SIZE;
        else
            copySize = size - offset;
        memcpy(chunk, data + offset, copySize);
        offset += copySize;

        // 发送数据块
        ssize_t sent = sendto(sockfd, chunk, copySize, 0, (struct sockaddr*)dest_addr, sizeof(*dest_addr));
        if (sent < 0) {
            printf("发送失败");
            return -1;
        }

        total_sent += sent;

        usleep(1000);    // 必须要延时
        current_chunk++;
    }

    return total_sent;
}

// 读取JPEG文件并转换为RGB565格式
int read_jpeg_file(FILE *file, dataType_e dataType, uint8_t **rgb_data, int *width, int *height, int *fileSize)
{
    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;
    JSAMPARRAY buffer;
    int row_stride;
    int pixel_count;
    int i, j, k;

    // 获取文件大小
    fseek(file, 0, SEEK_END);
    *fileSize = ftell(file);
    rewind(file);

    // 获取缓冲区倍率因子或直接加载jpeg
    uint8_t coe = 1;
    switch (dataType)
    {
    case GRAPH_JPG:
        *rgb_data = malloc(*fileSize);
        memset(*rgb_data, 0, *fileSize);
        size_t bytes_read = fread(*rgb_data, 1, *fileSize, file);
        if (bytes_read != *fileSize) {
            free(*rgb_data);
            printf("读取JPEG文件失败\n");
            return -1;
        }
        return 0;
    case GRAPH_RGB565:
    case GRAPH_RGB555:
        coe = sizeof(uint16_t);
        break;
    case GRAPH_GRAY8:
        coe = sizeof(uint8_t);
        break;
    default:
        printf("%s %s 不支持的帧类型\n", __FUNCTION__, __LINE__);
        return -1;
    }

    // 初始化JPEG错误处理
    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_decompress(&cinfo);

    // 指定数据源
    jpeg_stdio_src(&cinfo, file);

    // 读取文件头
    (void)jpeg_read_header(&cinfo, TRUE);

    // 设置解压参数
    cinfo.out_color_space = JCS_RGB;

    // 开始解压
    (void)jpeg_start_decompress(&cinfo);

    // 获取图像尺寸
    *width = cinfo.output_width;
    *height = cinfo.output_height;
    pixel_count = (*width) * (*height);

    // 分配RGB数据缓冲区
    *rgb_data = malloc(pixel_count * coe);
    if (*rgb_data == NULL) {
        fprintf(stderr, "内存分配失败\n");
        jpeg_finish_decompress(&cinfo);
        jpeg_destroy_decompress(&cinfo);
        return -1;
    }
    memset(*rgb_data, 0, pixel_count * coe);

    // 分配一行像素的缓冲区
    row_stride = cinfo.output_width * cinfo.output_components;
    buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1);

    // 逐行读取并转换为RGB
    k = 0;
    while (cinfo.output_scanline < cinfo.output_height) {
        (void)jpeg_read_scanlines(&cinfo, buffer, 1);

        // 处理当前行的每个像素
        for (i = 0; i < cinfo.output_width; i++) {
            uint8_t r = buffer[0][i*3];
            uint8_t g = buffer[0][i*3+1];
            uint8_t b = buffer[0][i*3+2];

            // 转换为RGB/GRAY并存储到缓冲区
            uint16_t pixelColor = 0;
            switch (dataType)
            {
            case GRAPH_RGB565:
                pixelColor = ((uint16_t)(r*32/256) << 11) | ((uint16_t)(g*64/256) << 5) | ((uint16_t)(b*32/256));
                ((uint16_t*)(*rgb_data))[k++] = pixelColor;
                break;
            case GRAPH_RGB555:
                pixelColor = ((uint16_t)(r*32/256) << 10) | ((uint16_t)(g*32/256) << 5) | ((uint16_t)(b*32/256));
                ((uint16_t*)(*rgb_data))[k++] = pixelColor;
                break;
            case GRAPH_GRAY8:
                pixelColor = (uint8_t)((299 * r + 587 * g + 114 * b + 500) / 1000); //RGB转灰度算法
                ((uint8_t*)(*rgb_data))[k++] = (uint8_t)pixelColor;
                break;
            default:
                printf("%s %s 不支持的帧类型\n", __FUNCTION__, __LINE__);
                break;
            }
        }
    }

    // 完成解压
    (void)jpeg_finish_decompress(&cinfo);

    // 释放JPEG资源
    jpeg_destroy_decompress(&cinfo);

    return 0;
}
