#include "PlayerGLWidget.h"
#include <QOpenGLFunctions> // 添加此行
#include <QApplication>

PlayerGLWidget::PlayerGLWidget(QWidget *parent) : QOpenGLWidget(parent)
{
    QString imagePath = QApplication::applicationDirPath() + "/0.jpg";
    QImage image(imagePath);
    convertQImageToYUV420(image, m_YUV420);
    /* 显示图片  */
    updateFrame(m_YUV420);
}

PlayerGLWidget::~PlayerGLWidget()
{

}

/* 刷新一帧 */
void PlayerGLWidget::updateFrame(Image_YUV420& image)
{
    yData = image.yData;
    uData = image.uData;
    vData = image.vData;
    imageSize_ = QSize(image.width, image.height);

    update();
}

/* 刷新一帧QImage */
void PlayerGLWidget::updateFrame(Image_QImage& image)
{
    m_image = image;

    update();
}

void PlayerGLWidget::convertQImageToYUV420(const QImage& image, Image_YUV420& yuv420)
{
    int width = image.width();
    int height = image.height();
    int ySize = width * height;
    int uvSize = ySize / 4;

    yuv420.width = width;
    yuv420.height = height;

    yuv420.yData.resize(ySize);
    yuv420.uData.resize(uvSize);
    yuv420.vData.resize(uvSize);

    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            QColor color = image.pixelColor(x, y);
            int r = color.red();
            int g = color.green();
            int b = color.blue();

            int yIndex = y * width + x;
            yuv420.yData[yIndex] = static_cast<unsigned char>((0.257 * r) + (0.504 * g) + (0.098 * b) + 16);

            if (y % 2 == 0 && x % 2 == 0) {
                int uvIndex = (y / 2) * (width / 2) + (x / 2);
                yuv420.uData[uvIndex] = static_cast<unsigned char>((-0.148 * r) - (0.291 * g) + (0.439 * b) + 128);
                yuv420.vData[uvIndex] = static_cast<unsigned char>((0.439 * r) - (0.368 * g) - (0.071 * b) + 128);
            }
        }
    }
}

void PlayerGLWidget::initializeGL()
{
    initializeOpenGLFunctions(); // 确保初始化 OpenGL 函数

    // 创建并编译顶点着色器
    const char* vertexShaderSource = R"(
        #version 330 core
        layout(location = 0) in vec3 aPos;
        layout(location = 1) in vec2 aTexCoord;
        out vec2 TexCoord;
        void main()
        {
            gl_Position = vec4(aPos, 1.0);
            TexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y); // 翻转纹理坐标
        }
    )";
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
    glCompileShader(vertexShader);

    // 创建并编译片段着色器
    const char* fragmentShaderSource = R"(
        #version 330 core
        out vec4 FragColor;
        in vec2 TexCoord;
        uniform sampler2D textureY;
        uniform sampler2D textureU;
        uniform sampler2D textureV;
        void main()
        {
            float y = texture(textureY, TexCoord).r;
            float u = texture(textureU, TexCoord).r - 0.5;
            float v = texture(textureV, TexCoord).r - 0.5;
            float r = y + 1.402 * v;
            float g = y - 0.344 * u - 0.714 * v;
            float b = y + 1.772 * u;
            FragColor = vec4(r, g, b, 1.0);
        }
    )";
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
    glCompileShader(fragmentShader);

    // 链接着色器程序
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader); // 确保传递的是程序对象和着色器对象
    glAttachShader(shaderProgram, fragmentShader); // 确保传递的是程序对象和着色器对象
    glLinkProgram(shaderProgram);

    // 删除着色器对象
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // 创建纹理
    glGenTextures(1, &textureIdY_);
    glGenTextures(1, &textureIdU_);
    glGenTextures(1, &textureIdV_);

    glBindTexture(GL_TEXTURE_2D, textureIdY_);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glBindTexture(GL_TEXTURE_2D, textureIdU_);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glBindTexture(GL_TEXTURE_2D, textureIdV_);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // 设置顶点数据和缓冲
    float vertices[] = {
        // positions          // texture coords
        -1.0f, -1.0f, 0.0f,  0.0f, 0.0f,
         1.0f, -1.0f, 0.0f,  1.0f, 0.0f,
         1.0f,  1.0f, 0.0f,  1.0f, 1.0f,
        -1.0f,  1.0f, 0.0f,  0.0f, 1.0f
    };
    unsigned int indices[] = {
        0, 1, 2,
        2, 3, 0
    };

    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    // 位置属性
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    // 纹理坐标属性
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}

void PlayerGLWidget::resizeGL(int w, int h)
{
    Ortho2DSize_.setWidth(w);
    Ortho2DSize_.setHeight(h);
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, Ortho2DSize_.width(), Ortho2DSize_.height(), 0, -1, 1);
    glMatrixMode(GL_MODELVIEW);
}

void PlayerGLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT);

    if (yData.isEmpty() || uData.isEmpty() || vData.isEmpty()) {
        return;
    }

    // 使用着色器程序
    glUseProgram(shaderProgram);

    // 更新纹理数据
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, textureIdY_);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, imageSize_.width(), imageSize_.height(), 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, yData.data());

    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, textureIdU_);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, imageSize_.width() / 2, imageSize_.height() / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, uData.data());

    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D, textureIdV_);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, imageSize_.width() / 2, imageSize_.height() / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, vData.data());

    // 设置纹理单元
    glUniform1i(glGetUniformLocation(shaderProgram, "textureY"), 0);
    glUniform1i(glGetUniformLocation(shaderProgram, "textureU"), 1);
    glUniform1i(glGetUniformLocation(shaderProgram, "textureV"), 2);

    // 绘制四边形
    glBindVertexArray(VAO);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);
}
