#include "playglwidget.h"
#include <QOpenGLContext>
#include <QApplication>
#include <QMouseEvent>
#include <QGSettings>
#include <QDateTime>
#include <QThread>
#include <QDebug>
#include <QTimer>
#include <ukui-log4qt.h>

#include "global/global.h"

using namespace Global;

static void *get_proc_address(void *ctx, const char *name) {
    Q_UNUSED(ctx);
    QOpenGLContext *glctx = QOpenGLContext::currentContext();
    if (!glctx)
        return NULL;
    return (void *)glctx->getProcAddress(QByteArray(name));
}

PlayGLWidget::PlayGLWidget(QWidget *parent)
    : QOpenGLWidget(parent),
      m_screenScale(1.0),
      mpv_gl(nullptr)
{
    setlocale(LC_NUMERIC, "C");
    setMouseTracking(true);

    m_dbClicked = false;
    m_mouseUsed = true;

    initGlobalSig();

    m_checkMouseTimer = new QTimer;
    m_checkMouseTimer->setInterval(2000);
    connect(m_checkMouseTimer, &QTimer::timeout, [&](){
        if(!m_hasVideo)
            return;
        if(m_isMouseEnter) {
            if (m_mouseUsed)
                setCursor(QCursor(Qt::BlankCursor));
        }
        g_user_signal->hideBar(true);

        m_checkMouseTimer->stop();
    });

    m_lMouseClickTimer = new QTimer;
    m_lMouseClickTimer->setInterval(300);
    connect(m_lMouseClickTimer, &QTimer::timeout, [&](){
        if (m_dbClicked) {
            m_lMouseClickTimer->stop();
            return;
        }
        emit mousePressed();
        m_lMouseClickTimer->stop();
    });
}

PlayGLWidget::~PlayGLWidget()
{
}

void PlayGLWidget::swapped()
{
    mpv_opengl_cb_report_flip(mpv_gl, 0);
}

void PlayGLWidget::on_update(void *ctx)
{
    QMetaObject::invokeMethod((PlayGLWidget*)ctx, "update");
}

void PlayGLWidget::initMpvGL()
{
    if(mpv_h)
    {
        mpv_gl = (mpv_opengl_cb_context *)mpv_get_sub_api(mpv_h, MPV_SUB_API_OPENGL_CB);
        if (!mpv_gl)
        {
            KyInfo() << "get sub api error";
            return;
        }
        mpv_opengl_cb_set_update_callback(mpv_gl, PlayGLWidget::on_update, (void *)this);
        connect(this, &PlayGLWidget::frameSwapped, this, &PlayGLWidget::swapped);

        int r = mpv_opengl_cb_init_gl(mpv_gl, NULL, get_proc_address, NULL);
        if (r < 0)
        {
            KyInfo("could not initialize OpenGL");
        }
    }
}

void PlayGLWidget::initGlobalSig()
{
    connect(g_core_signal, &GlobalCoreSignal::sigStateChange, [&](){
        if (g_playstate == Mpv::Playing) {
            m_screenScale = qApp->devicePixelRatio();
        }
        else if (g_playstate == Mpv::Stopped) {
            update();
        }
    });

    connect(g_core_signal, &GlobalCoreSignal::sigStateChange, this, &PlayGLWidget::playStateChange);
    connect(g_core_signal, &GlobalCoreSignal::sigVideoIdChange, this, &PlayGLWidget::videIdChange);
}

void PlayGLWidget::initializeGL()
{
    if(mpv_gl)
    {
        int r = mpv_opengl_cb_init_gl(mpv_gl, NULL, get_proc_address, NULL);
        if (r < 0)
        {
            KyInfo("could not initialize OpenGL");
        }
    }
}

void PlayGLWidget::paintGL()
{
    if(mpv_gl)
    {
        mpv_opengl_cb_draw(mpv_gl,
                           this->defaultFramebufferObject(),
                           this->width()*m_screenScale,
                           -this->height()*m_screenScale);
    }
}

void PlayGLWidget::setMouseUsed(bool used)
{
    m_mouseUsed = used;
    if (!m_mouseUsed) {
        setCursor(QCursor(Qt::ArrowCursor));
        m_checkMouseTimer->stop();
    }
}

void PlayGLWidget::playStateChange()
{
    if(g_playstate < 0) {
        m_checkMouseTimer->stop();
    }
    else {
        m_checkMouseTimer->start();
    }
}

void PlayGLWidget::videIdChange(int vid)
{
    if(vid < 0)
        m_hasVideo = false;
    else
        m_hasVideo = true;
}


void PlayGLWidget::mousePressEvent(QMouseEvent *e)
{
    m_isMousePressed = true;
    m_mousePosPressed = e->pos();
    m_posStart = e->pos();
    m_posLast = e->pos();

    // 右键点击触发显示菜单
    if (e->button() == Qt::LeftButton) {
        m_timePressStart = QDateTime::currentMSecsSinceEpoch();
    }
    return QOpenGLWidget::mousePressEvent(e);
}

void PlayGLWidget::mouseReleaseEvent(QMouseEvent *e)
{
    m_isMousePressed = false;
    // 左键离开触发暂停，如果左键按得时间很长就不触发了，不然会和触摸屏长按冲突
    if (e->button() == Qt::LeftButton && (QDateTime::currentMSecsSinceEpoch() - m_timePressStart) < 500) {
        if (!m_mouseUsed)
            return QOpenGLWidget::mouseReleaseEvent(e);
        if (e->pos() == m_mousePosPressed) {
            m_lMouseClickTimer->start();
        }
    }
    return QOpenGLWidget::mouseReleaseEvent(e);
}

void PlayGLWidget::mouseMoveEvent(QMouseEvent *e)
{
    if (m_isMousePressed) {
        m_posCurrent = e->pos();
        int xc = abs(m_posCurrent.x() - m_posLast.x());
        int yc = abs(m_posCurrent.y() - m_posLast.y());
        if (xc < yc) {
            m_volumeChange = yc * 200 / height();
            //符合音量调节
            if (m_volumeChange > 0) {
                if (m_posCurrent.y() - m_posLast.y() > 2) {
                    g_user_signal->setVolumeDown(m_volumeChange);
                    m_posLast = m_posCurrent;
                }
                else {
                    g_user_signal->setVolumeUp(m_volumeChange);
                    m_posLast = m_posCurrent;
                }
            }
        }
    }

    m_isMouseEnter = true;
    m_checkMouseTimer->stop();
    setCursor(QCursor(Qt::ArrowCursor));
    g_user_signal->hideBar(false);
    if(g_playstate > 0)
        m_checkMouseTimer->start();
    e->accept();
}

void PlayGLWidget::mouseDoubleClickEvent(QMouseEvent *e)
{
    if (!m_mouseUsed)
        return QOpenGLWidget::mouseDoubleClickEvent(e);
    if(e->button() == Qt::LeftButton) {
        g_user_signal->fullScreen();
        m_dbClicked = true;
        QTimer::singleShot(500, [this]{m_dbClicked = false;});
        m_lMouseClickTimer->stop();
    }
    return QOpenGLWidget::mouseDoubleClickEvent(e);
}

void PlayGLWidget::wheelEvent(QWheelEvent *e)
{
    // 鼠标滚轮和触控板双指滑动调节音量
    int wheel_distance = e->delta();
    if (abs(wheel_distance) / 120 == 1) {
        if (wheel_distance > 0)
            g_user_signal->setVolumeUp(5);
        else
            g_user_signal->setVolumeDown(5);
    }
    return QOpenGLWidget::wheelEvent(e);
}

void PlayGLWidget::enterEvent(QEvent *e)
{
    m_isMouseEnter = true;
    e->accept();
}

void PlayGLWidget::leaveEvent(QEvent *e)
{
    m_isMousePressed = false;
    m_isMouseEnter = false;
    if(g_playstate > 0)
        m_checkMouseTimer->start();

    return QOpenGLWidget::leaveEvent(e);
}

