#include "glview.h"
#include <QMouseEvent>
#include <qdebug.h>

GLView::GLView(QWidget* parent)
    : QOpenGLWidget{ parent }
{
}

GLView::~GLView()
{
    makeCurrent();
    delete m_model;

    doneCurrent();
}

void GLView::initializeGL()
{
    initializeOpenGLFunctions();
    glEnable(GL_DEPTH_TEST);
    //glEnable(GL_CULL_FACE);
    /*glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);*/

    initShader(m_lightShader, "./shader/modelLoading.vert", "./shader/modelLoading.frag");
    initShader(m_viewCubeShader, "./shader/viewCubeTexture.vert", "./shader/viewCubeTexture.frag");

    m_model = new Model(this);
    m_camera.lastFrame = QTime::currentTime().msecsSinceStartOfDay() / 1000.0;

    initWorkPlane();
    //m_viewMat.lookAt(QVector3D(0, 0, 5), QVector3D(0, 0, 0), QVector3D(0, 1, 0));
   
    m_viewCube = new ViewCube(this, ":/MainWindow/resources/viewcube.png", width(), height());
}

void GLView::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);

    m_camera.SCR_WIDTH = w;
    m_camera.SCR_HEIGHT = h;

    m_projectionMat.setToIdentity();
    m_projectionMat.perspective(/*qDeg
reesToRadians*/(m_camera.Zoom), (float)m_camera.SCR_WIDTH / (float)m_camera.SCR_HEIGHT, 0.1f, 100.0f);
    //m_projectionMat.perspective(45.0f, (float)w / h, 0.1f, 100.0f);
}

void GLView::paintGL()
{
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    float currentFrame = QTime::currentTime().msecsSinceStartOfDay() / 1000.0;
    m_camera.deltaTime = currentFrame - m_camera.lastFrame;
    m_camera.lastFrame = currentFrame;

    m_lightShader.bind();

    m_viewMat = m_camera.GetViewMatrix();

    m_lightShader.setUniformValue("projection", m_projectionMat);
    m_lightShader.setUniformValue("view", m_viewMat);
    m_lightShader.setUniformValue("model", m_modelMat);

    m_model->Draw(m_lightShader);
    m_workPlane->drawPlane();

    //-------------------未封装到Model类中的绘制版本-------------------------

    // 2. 绘制ViewCube（使用纹理着色器）
    if (m_viewCube) 
    {
        m_viewCubeShader.bind(); // 绑定纹理着色器

        //model矩阵: 缩放cubeScale
        m_modelCube.setToIdentity();
        float cubeScale = 0.5f;
        m_modelCube.scale(cubeScale);

        // View矩阵
        m_viewMatNoTrans = m_camera.GetViewMatrix4VieweCube();

        // Projection矩阵：透视投影 + 裁剪空间偏移（核心：固定到右上角）
        // 基础透视投影
        m_projection4ViewCube.setToIdentity();
        float aspect = (float)width() / height(); // 窗口宽高比（替换为你的宽高获取方式）
        m_projection4ViewCube.perspective(45.0f, aspect, 0.1f, 100.0f);

        // 投影后偏移矩阵（在裁剪空间偏移，将viewCube推到右上角）
        QMatrix4x4 offViewCube;
        offViewCube.setToIdentity();
        // 裁剪空间偏移：X正方向右移，Y正方向上移（范围[-1,1]，0.85/0.7为右上角典型值）
        QVector2D projOffset(0.90f, 0.80f);// 裁剪空间偏移（控制右上角位置，范围[-1,1]）
        offViewCube.translate(projOffset.x(), projOffset.y(), 0.0f);

        // 最终投影矩阵 = 偏移矩阵 × 基础透视投影
        m_finalProjection = offViewCube * m_projection4ViewCube;//将视图立方体固定在左上角的核心代码：施加投影矩阵后再施加一个偏移offViewCube，而不是先施加平移矩阵再投影

        // 传递矩阵给着色器
        m_viewCubeShader.setUniformValue("model", m_modelCube);         // 原点位置的viewCube
        m_viewCubeShader.setUniformValue("view", m_viewMatNoTrans);     // 看向原点的view矩阵
        m_viewCubeShader.setUniformValue("projection", m_finalProjection); // 带偏移的投影矩阵

        // 绘制viewCube
        m_viewCube->draw(m_viewCubeShader, m_modelCube, m_viewMatNoTrans, m_finalProjection);

        m_viewCubeShader.release(); // 解绑着色器
    }

    m_lightShader.release();
}

void GLView::initShader(QOpenGLShaderProgram& shader, const QString& vertexFile, const QString& fragFile)
{
    bool result = true;
    result = shader.addShaderFromSourceFile(QOpenGLShader::Vertex, vertexFile);
    if (!result) {
        qDebug() << shader.log();
    }

    result = shader.addShaderFromSourceFile(QOpenGLShader::Fragment, fragFile);
    if (!result) {
        qDebug() << shader.log();
    }
    result = shader.link();
    if (!result) {
        qDebug() << shader.log();
    }
}

bool GLView::event(QEvent* e)
{
    makeCurrent();
    
    if (e->type() == QEvent::MouseButtonPress)
    {
        auto mouseEvent = static_cast<QMouseEvent*>(e);
        if (mouseEvent->button() == Qt::LeftButton)
        {
            ViewCube::CubeFaceType face = m_viewCube->getFirstHitFace(mouseEvent->position().x(), mouseEvent->position().y(),width(),height(), m_viewMatNoTrans, m_finalProjection);
            if (face != ViewCube::CubeFaceType::None)
            {
                m_camera.FitView(static_cast<int>(face));
            }
        }
    }

    if (m_camera.handle(e))
        update();

    doneCurrent();
    return QWidget::event(e);
}

void GLView::initWorkPlane()
{
    PlanePara para;
    para.origin = QVector3D(0.0f, -1.0f, 0.0f);//原点
    para.normal = QVector3D(0.0f, 1.0f, 0.0f); //法向
    para.halfLength = 15.0f;
    para.gridCntPerEdge = 12;
    para.offset = 0.0f;

    m_workPlane = new WorkPlane();
    m_workPlane->initPlane(para);
}