#include "VideoPlayer.h"

#include "DecodeVedio.h"

#include <QPainter>
#include <QResizeEvent>
#include <QEventLoop>

#include "spdlog/spdlog.h"



VideoPlayer::VideoPlayer(QWidget *parent) : QWidget(parent)
{
    /* 初始化解码线程 */
    m_threadDecode = new QThread(this);
    m_decodeVedio = new DecodeVedio(m_threadDecode);

    m_semRefresh = new QSemaphore(0);

    m_timerRefreshUI.setSingleShot(false);
    /* 设置精度毫秒级 */
    m_timerRefreshUI.setTimerType(Qt::PreciseTimer);
    connect(&m_timerRefreshUI, &QTimer::timeout, this, &VideoPlayer::do_refreshUI);

    connect(m_decodeVedio, &DecodeVedio::signal_oneImage, this, &VideoPlayer::do_refreshOneUI);
    connect(m_decodeVedio, &DecodeVedio::signal_playCompleted, this, &VideoPlayer::do_playCompleted);
    SPDLOG_TRACE("UI线程ID:{}", QThread::currentThreadId());
}

VideoPlayer::~VideoPlayer()
{
    if(m_timerRefreshUI.isActive())
    {
        m_timerRefreshUI.stop();
    }
    delete m_decodeVedio;
    if(m_image)
    {
        delete m_image;
    }
}

/**
 * @brief 设置播放视频,启动定时器,定时器间隔决定播放的速度
 *        视频的宽和高使用QImage进行缩放
 *        视频大小在直接设置这个类的resize即可,有最小大小限制
 * 
 * @param fileName 
 */
void VideoPlayer::setPlayVedio(const QString& fileName)
{
    if(isSetVedioFile)
    {
        isSetVedioFile = false;
    }
    if(m_decodeVedio->isInitFFmpeg())
    {
        m_decodeVedio->unInitFFmpeg();
    }
    m_fileName = fileName;
    isSetVedioFile = true;
    m_decodeVedio->initFFmpeg(m_fileName);
    // m_decodeVedio->setVideoSize(this->width(), this->height());
    /* 获取原始视频信息 */
    m_srcWidth = m_decodeVedio->getSrcVideoWidth();
    m_srcHeight = m_decodeVedio->getSrcVideoHeight();
    m_frameCount = m_decodeVedio->getFrameCount();
    SPDLOG_DEBUG("视频宽:{} 高:{} 帧数:{}", m_srcWidth, m_srcHeight, m_frameCount);
    /* 设置视频宽和高的最小大小 */
    this->setMinimumSize(160,90);
    /* 开启定时器刷新 */
    if(m_frameCount < 0)
    {
        /* HEVC帧率,获取不到,就按照24帧来刷新 */
        if(m_frameCount == -2)
        {
            m_frameCount = 24;
        }
        else {
            m_frameCount = 25;
        }
    }
    else if(m_frameCount == 0)
    {
        m_frameCount = 25;
    }
    SPDLOG_INFO("帧率:{}", m_frameCount);

    /* 开启解码,手动刷新第一帧 */
    m_decodeVedio->startDecodeVedio();
    m_semRefresh->release(2);
    // m_timerRefreshUI.setSingleShot(true);
    // m_timerRefreshUI.start(500);
}

/* 播放视频 */
bool VideoPlayer::play()
{
    if(!isSetVedioFile)
    {
        SPDLOG_ERROR("文件名为空");
        return false;
    }
    if(m_playStatus)
    {
        return false;
    }
    
    /* 设置刷新时间 */
    m_timerRefreshUI.setSingleShot(false);
    m_interval = 1000/m_frameCount;
    if(1000 % m_frameCount > 5)
    {
        m_frameCount += 1;
    }
    SPDLOG_TRACE("刷新UI的定时间隔:{}",m_interval);
    m_timerRefreshUI.start(m_interval);
    m_playStatus = true;
    
    return true;
}

/* 暂停播放 */
void VideoPlayer::pause()
{
    if(!m_playStatus)
    {
        return;
    }
    m_timerRefreshUI.stop();
    m_playStatus = false;
}

/* 停止播放,停止后停止解码,将时间等复位到开始时间 */
void VideoPlayer::stop()
{
    SPDLOG_DEBUG("...停止播放...");
    // m_fileName = QString();
    if(m_timerRefreshUI.isActive())
    {
        m_timerRefreshUI.stop();
    }
    // SPDLOG_DEBUG("...停止解码...");
    
    /* 重新设置播放视频 */
    setPlayVedio(m_fileName);

    /* 绘制黑帧 */
    // SPDLOG_DEBUG("绘制黑帧");
    // m_image = new QImage(m_nowWidth, m_nowHeight, QImage::Format_RGB32);
    // m_image->fill(Qt::black);
    // update();
    m_playStatus = false;
    // isSetVedioFile = false;
}

/* 获取视频时长 */
qint64 VideoPlayer::getDuration()
{
    return m_decodeVedio->getDuration();
}

/* 获取当前播放位置 */
qint64 VideoPlayer::getCurrentPos()
{
    return m_decodeVedio->getCurrentPos();
}

/* 设置当前播放位置 */
void VideoPlayer::setCurrentPos(quint64 pos)
{
    /* 先停止播放 */
    bool temp = m_playStatus;
    if(m_playStatus)
    {
        m_timerRefreshUI.stop();
        m_playStatus = false;
    }
    m_decodeVedio->setCurrentPos(pos);
    /* 继续播放 */
    if(temp)
    {
        // SPDLOG_INFO("..........开启定时器..........");
        m_timerRefreshUI.start(m_interval);
        m_playStatus = true;
    }else
    {
        /* 刷新5张照片,防止第一张是跳转前的时间段 */
        m_semRefresh->release(5);
    }
}

/* 设置播放视频大小 */
void VideoPlayer::setPlayVedioSize(int width,int height)
{
    /* 对宽和高就行缩放,保持比例,同时将其居中放置
     * 先计算出比例,和16/9相对比
     * 大于16/9,以高为最大极限,计算出宽度和x坐标
     * 小于16/9,以宽为最大极限,计算出高度和y坐标 */
    double srcRatio = m_srcWidth*1.0 / m_srcHeight;
    double ratio = width*1.0 / height;
    long w1 = 0, h1 = 0;
    int srcX = this->pos().rx(), srcY = this->pos().ry();
    int x1 = srcX, y1 = srcY;
    if(ratio > srcRatio)
    {
        w1 = height * srcRatio;
        x1 = (width - w1) / 2;
        h1 = height;
        y1 = srcY;
    }
    else if(ratio < srcRatio)
    {
        h1 = width / srcRatio;
        y1 = (height - h1) / 2;
        w1 = width;
        x1 = srcX;
    }else {
        w1 = width;
        h1 = height;
        x1 = srcX;
        y1 = srcY;
    }
    this->move(x1, y1);
    
    m_nowWidth = w1;
    m_nowHeight = h1;
    this->resize(w1, h1);
    // SPDLOG_DEBUG("设置窗口位置:{}x{}, 大小:{}x{}, 传入大小:{}x{}", x1, y1, w1, h1, width, height);
    SPDLOG_DEBUG("现在位置和大小:{}x{}, {}x{}", this->pos().rx(), this->pos().ry(), this->width(), this->height());
}

/* 设置播放回调函数 */
void VideoPlayer::setPlayCallBack(std::function<Play_CallBack> playCallBack,void* context)
{
    m_funcPlayCB = playCallBack;
    m_context = context;
}


void VideoPlayer::paintEvent(QPaintEvent *event)
{
    if(m_image)
    {
        // SPDLOG_TRACE("开始绘制画面...");
        /* 对图像进行缩放 */
        QImage image;
        if(m_srcWidth != m_nowWidth || m_srcHeight != m_nowHeight)
        {
            image = m_image->scaled(m_nowWidth, m_nowHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation);
        }
        QPainter painter(this);
        painter.drawImage(0, 0, image);
    }
}

void VideoPlayer::resizeEvent(QResizeEvent *event)
{
    SPDLOG_TRACE("窗口大小改变...");
    m_nowWidth = event->size().width();
    m_nowHeight = event->size().height();

    /* 传递给解码器 */
    // m_decodeVedio->setVideoSize(m_nowWidth, m_nowHeight);

    QWidget::resizeEvent(event);
}

/* 刷新一张图片,直到有图片为止 */
void VideoPlayer::refreshOneUIUntilHave()
{
    if(m_decodeVedio != nullptr)
    {
        // SPDLOG_DEBUG("取出一帧图片...");
        /* 删除上一帧图片 */
        if(m_image != nullptr)
        {
            delete m_image;
            m_image = nullptr;
        }
        /* 如果没有图片,这个函数会阻塞 */
        m_image = m_decodeVedio->getOneImageUntilHave();
        
        if(m_image)
        {
            // if(m_srcWidth != m_nowWidth || m_srcHeight != m_nowHeight)
            // {
            //     *m_image = m_image->scaled(m_nowWidth, m_nowHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation);
            // }
            // SPDLOG_DEBUG("绘制画面...");
            update();
        }
        m_decodeVedio->wakeUpCondQueueNoEmpty();
    }
}


/* 双击事件函数 */
void VideoPlayer::mouseDoubleClickEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        // SPDLOG_DEBUG("双击事件...");
        if(m_funcPlayCB != nullptr)
        {
            m_funcPlayCB(this, 5, nullptr, 0, m_context);
        }else {
            SPDLOG_INFO("没有设置回调函数");
        }
    }
}

/* 取出画面,刷新UI */
void VideoPlayer::do_refreshUI()
{
    if(m_decodeVedio != nullptr)
    {
        // SPDLOG_DEBUG("取出一帧图片...");
        /* 删除上一帧图片 */
        if(m_image != nullptr)
        {
            delete m_image;
            m_image = nullptr;
        }
        m_image = m_decodeVedio->getOneImage();
        
        if(m_image)
        {
            if(m_srcWidth != m_nowWidth || m_srcHeight != m_nowHeight)
            {
                *m_image = m_image->scaled(m_nowWidth, m_nowHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation);
            }
            // SPDLOG_DEBUG("绘制画面...");
            update();
        }
        m_decodeVedio->wakeUpCondQueueNoEmpty();
    }
}


/* 通过信号刷新第一张图片 */
void VideoPlayer::do_refreshOneUI()
{
    if(!m_semRefresh->tryAcquire(1))
    {
        return;
    }
    /* 取出第一张 */
    if(m_decodeVedio != nullptr)
    {
        // SPDLOG_DEBUG("取出一帧图片...");
        /* 删除上一帧图片 */
        if(m_image != nullptr)
        {
            delete m_image;
            m_image = nullptr;
        }
        m_image = m_decodeVedio->getOneImage();
        
        if(m_image)
        {
            if(m_srcWidth != m_nowWidth || m_srcHeight != m_nowHeight)
            {
                *m_image = m_image->scaled(m_nowWidth, m_nowHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation);
            }
            SPDLOG_DEBUG("绘制预览画面...");
            update();
        }
        m_decodeVedio->wakeUpCondQueueNoEmpty();
    }
}

/* 播放完成 */
void VideoPlayer::do_playCompleted()
{
    SPDLOG_INFO("Video 播放完成...");
    m_timerRefreshUI.stop();
    m_playStatus = false;
    if(m_funcPlayCB != nullptr)
    {
        /* 播放完成的回调函数 */
        m_funcPlayCB(this, 2, nullptr, 0, m_context);
    }
}