/*
 * Kylin-video
 *
 * Copyright (C) 2021, Tianjin KYLIN Information Technology Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * Authors: Liu Cong <liucong1@kylinos.cn>
 *
 */

#include "progressbar.h"

#include <QDebug>
#include <QEvent>
#include <QToolTip>
#include <QMouseEvent>

#include "global/functions.h"
#include "global/global.h"
#include "sliderbar.h"

ProgressBar::ProgressBar(QWidget *parent) :
    QWidget(parent),
    m_widgetDock(nullptr),
    m_valueBar(nullptr),
    m_maxValue(0),
    m_minValue(0)
{
    m_canChange = true;

    setAttribute(Qt::WA_TranslucentBackground, true);

    m_widgetDock = new QWidget(this);
    m_widgetDock->setObjectName("progress");
    m_widgetDock->setStyleSheet("#progress{background-color:rgba(255,255,255,26); border-radius:2px;}");
    m_widgetDock->setCursor(Qt::PointingHandCursor);

    m_valueBar = new QWidget(m_widgetDock);
    m_valueBar->resize(0, DEFAULT_HEIGHT);
    m_valueBar->setFixedHeight(DEFAULT_HEIGHT);
    m_valueBar->setStyleSheet(QString("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, "
                              "stop:0 rgba(41, 134, 255, 255), stop:1 rgba(62, 255, 254, 255));"
                              "border-radius:%1px;").arg(DEFAULT_HEIGHT/2));

    m_valueBar->setMouseTracking(true);
    setMouseTracking(true);
    m_widgetDock->setMouseTracking(true);

    connect(g_core_signal, &GlobalCoreSignal::sigStateChange, [this](Mpv::PlayState st){if (st == Mpv::Stopped) m_canChange = true;});
}

void ProgressBar::setRange(int min, int max)
{
    if (min > max) {
        return;
    }
    m_minValue = min;
    m_maxValue = max;
    m_currentValue = 0;
    m_valueBar->resize(0, DEFAULT_HEIGHT);
}

void ProgressBar::setValue(int value)
{
    if (!m_canChange) {
        return;
    }
    if (value < m_minValue || value > m_maxValue) {
        return;
    }
    m_currentValue = value;

    if (m_maxValue != m_minValue)
        m_valueBar->resize((m_currentValue - m_minValue) * width() / (m_maxValue - m_minValue), DEFAULT_HEIGHT);
}

void ProgressBar::setSlider(Slider *sl)
{
    m_slider = sl;
    // 拖动滑块改变显示进度
    connect(m_slider, &Slider::posXUpdate, [this](int x){
        m_valueBar->resize(x - 8 + m_slider->width() / 2, DEFAULT_HEIGHT);
        setToolTip(QString::number(w2v(m_valueBar->width())));
        updateMouseValue(m_valueBar->width());
    });
    connect(m_slider, &Slider::lockProgress, [this](bool flag) {
        // 如果锁定进度条，则说明不能外部更新 value
        m_canChange = !flag;
        // 滑块释放之后 value 需要通知外部
        if (m_canChange) {
            emit valueChange(m_mouseValue);
        }
    });
}

/**
** @brief     : 更新滑块位置，如果整体大小发生改变的话
** @param[in] :
** @param[out]:
** @return    :
***/
void ProgressBar::updateSliderPos()
{
    m_slider->move(DEFAULT_LR_MARGIN + m_valueBar->width() - (SLIDER_SIDE_SIZE / 2),
                   (parentWidget()->height() - SLIDER_SIDE_SIZE) / 2);

    for (FixedSlider *fs : m_markList) {
        fs->move(fs->x(), (parentWidget()->height() - SLIDER_MARK_HEIGHT) / 2);
    }
}

/**
** @brief     : 添加书签
** @param[in] : value 书签的进度值（秒），desc 书签描述
** @param[out]:
** @return    :
***/
void ProgressBar::addMark(int value, QString desc)
{
    FixedSlider *fs = new FixedSlider(parentWidget());
    connect(fs, &FixedSlider::clicked, [this, fs](){
        m_currentValue = fs->value;
        updateMouseValue(fs->x() - DEFAULT_LR_MARGIN + fs->width() / 2);
        emit valueChange(fs->value);
    });
    fs->value = value * 100;
    fs->move(v2w(fs->value) + DEFAULT_LR_MARGIN - fs->width() / 2,
             (parentWidget()->height() - fs->height()) / 2);
    fs->setDescribe(desc);
    fs->show();
    fs->raise();

    m_markList.push_back(fs);
}

void ProgressBar::deleteMark(int value)
{
    int i=0;
    for (FixedSlider *fs : m_markList) {
        if (fs->value == value * 100) {
            delete fs;
            break;
        }
        i++;
    }
    m_markList.removeAt(i);
}

void ProgressBar::clearMark()
{
    for (FixedSlider *fs : m_markList) {
        delete fs;
    }
    m_markList.clear();
}

void ProgressBar::setBlackTheme()
{
    m_widgetDock->setStyleSheet("#progress{background-color:rgba(255,255,255,50); border-radius:2px;}");
}

void ProgressBar::setLightTheme()
{
    m_widgetDock->setStyleSheet("#progress{background-color:rgba(48,49,51,50); border-radius:2px;}");
}

/**
** @brief     : width 转 value
** @param[in] :
** @param[out]:
** @return    :
***/
int ProgressBar::w2v(int width)
{
    return width * (m_maxValue - m_minValue) / this->width() + m_minValue;
}

/**
** @brief     : value 转 width
** @param[in] :
** @param[out]:
** @return    :
***/
int ProgressBar::v2w(int value)
{
    if (m_maxValue != m_minValue)
        return (value - m_minValue) * width() / (m_maxValue - m_minValue);
    return 1;
}

void ProgressBar::updateMouseValue(int vb_x)
{
    if (vb_x < 0) {
        vb_x = 0;
    }
    else if (vb_x > width()) {
        vb_x = width();
    }
    m_valueBar->resize(vb_x, height());

    m_mouseValue = w2v(m_valueBar->width());
    m_slider->move(DEFAULT_LR_MARGIN + vb_x - (SLIDER_SIDE_SIZE / 2),
                   (parentWidget()->height() - SLIDER_SIDE_SIZE) / 2);
    emit sliderMoved(m_mouseValue);
}

void ProgressBar::enterEvent(QEvent *e)
{
    m_slider->show();
    m_slider->raise();
}

void ProgressBar::leaveEvent(QEvent *e)
{
    m_slider->setHide();
    emit mouseLeave();
}

void ProgressBar::resizeEvent(QResizeEvent *e)
{
    m_widgetDock->resize(size());
    if (m_maxValue != m_minValue)
        m_valueBar->resize((m_currentValue - m_minValue) * width() / (m_maxValue - m_minValue), DEFAULT_HEIGHT);

    for (FixedSlider *fs : m_markList) {
        fs->move(v2w(fs->value) + DEFAULT_LR_MARGIN - fs->width() / 2,
                 (parentWidget()->height() - fs->height()) / 2);
    }
}

void ProgressBar::mouseMoveEvent(QMouseEvent *e)
{
    emit mousePosChange(w2v(e->x())/100);
//    setToolTip(Functions::timeToStr(w2v(e->x())/100));
    if (!m_canChange)
        updateMouseValue(e->x());
}

void ProgressBar::mousePressEvent(QMouseEvent *e)
{
    if (e->button() == Qt::LeftButton) {
        m_canChange = false;
        updateMouseValue(e->x());
    }
}

void ProgressBar::mouseReleaseEvent(QMouseEvent *e)
{
    if (e->button() == Qt::LeftButton) {
        emit valueChange(m_mouseValue);
        m_canChange = true;
    }
}
