/***************************************************************************
 *   Copyright (C) 2010 by Simon Andreas Eugster (simon.eu@gmail.com)      *
 *   This file is part of kdenlive. See www.kdenlive.org.                  *
 *                                                                         *
 *   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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/

#include <QPainter>
#include <QPoint>
#include <QMenu>

// For reading out the project resolution
#include "kdenlivesettings.h"
#include "profilesdialog.h"

#include "waveform.h"
#include "colorcorrection/waveformgenerator.h"


const QSize Waveform::m_textWidth(35,0);
const int Waveform::m_paddingBottom(20);

Waveform::Waveform(QWidget *parent) :
    AbstractGfxScopeWidget(true, parent)
  ,ui(NULL)
{
    ui = new Ui::Waveform_UI();
    ui->setupUi(this);

    ui->paintMode->addItem(i18n("Yellow"), QVariant(WaveformGenerator::PaintMode_Yellow));
    ui->paintMode->addItem(i18n("White"), QVariant(WaveformGenerator::PaintMode_White));
    ui->paintMode->addItem(i18n("Green"), QVariant(WaveformGenerator::PaintMode_Green));


    m_aRec601 = new QAction(i18n("Rec. 601"), this);
    m_aRec601->setCheckable(true);
    m_aRec709 = new QAction(i18n("Rec. 709"), this);
    m_aRec709->setCheckable(true);
    m_agRec = new QActionGroup(this);
    m_agRec->addAction(m_aRec601);
    m_agRec->addAction(m_aRec709);
    m_menu->addSeparator()->setText(i18n("Luma mode"));
    m_menu->addAction(m_aRec601);
    m_menu->addAction(m_aRec709);


    connect(ui->paintMode, SIGNAL(currentIndexChanged(int)), this, SLOT(forceUpdateScope()));
    connect(this, SIGNAL(signalMousePositionChanged()), this, SLOT(forceUpdateHUD()));
    connect(m_aRec601, SIGNAL(toggled(bool)), this, SLOT(forceUpdateScope()));
    connect(m_aRec709, SIGNAL(toggled(bool)), this, SLOT(forceUpdateScope()));

    init();
    m_waveformGenerator = new WaveformGenerator();
}

Waveform::~Waveform()
{
    writeConfig();

    delete m_waveformGenerator;
    delete m_aRec601;
    delete m_aRec709;
    delete m_agRec;
    delete ui;
}

void Waveform::readConfig()
{
    AbstractGfxScopeWidget::readConfig();

    KSharedConfigPtr config = KGlobal::config();
    KConfigGroup scopeConfig(config, configName());
    ui->paintMode->setCurrentIndex(scopeConfig.readEntry("paintmode", 0));
    m_aRec601->setChecked(scopeConfig.readEntry("rec601", false));
    m_aRec709->setChecked(!m_aRec601->isChecked());
}

void Waveform::writeConfig()
{
    KSharedConfigPtr config = KGlobal::config();
    KConfigGroup scopeConfig(config, configName());
    scopeConfig.writeEntry("paintmode", ui->paintMode->currentIndex());
    scopeConfig.writeEntry("rec601", m_aRec601->isChecked());
    scopeConfig.sync();
}


QRect Waveform::scopeRect()
{
    // Distance from top/left/right
    int offset = 6;
    QPoint topleft(offset, ui->verticalSpacer->geometry().y()+offset);

    return QRect(topleft, this->size() - QSize(offset+topleft.x(), offset+topleft.y()));
}


///// Implemented methods /////

QString Waveform::widgetName() const { return QString("Waveform"); }
bool Waveform::isHUDDependingOnInput() const { return false; }
bool Waveform::isScopeDependingOnInput() const { return true; }
bool Waveform::isBackgroundDependingOnInput() const { return false; }

QImage Waveform::renderHUD(uint)
{
    QImage hud(m_scopeRect.size(), QImage::Format_ARGB32);
    hud.fill(qRgba(0,0,0,0));

    QPainter davinci(&hud);
    davinci.setPen(penLight);

    QMap< QString, QString > values = ProfilesDialog::getSettingsFromFile(KdenliveSettings::current_profile());
//    qDebug() << values.value("width");

    const int rightX = scopeRect().width()-m_textWidth.width()+3;
    const int x = m_mousePos.x() - scopeRect().x();
    const int y = m_mousePos.y() - scopeRect().y();

    if (scopeRect().height() > 0 && m_mouseWithinWidget) {
        const int top = 30;
        const int bottom = 20;
        int val = 255*(1-(float)y/scopeRect().height());

        if (val >= 0 && val <= 255) {
            // Draw a horizontal line through the current mouse position
            // and show the value of the waveform there
            davinci.drawLine(0, y, scopeRect().size().width()-m_textWidth.width(), y);

            // Make the value stick to the line unless it is at the top/bottom of the scope
            int valY = y+5;
            if (valY < top) {
                valY = top;
            } else if (valY > scopeRect().height()-bottom) {
                valY = scopeRect().height()-bottom;
            }
            davinci.drawText(rightX, valY, QVariant(val).toString());
        }

        if (scopeRect().width() > 0) {
            // Draw a vertical line and the x position of the source clip
            bool ok;
            const int profileWidth = values.value("width").toInt(&ok);

            if (ok) {
                const int clipX = (float)x/(scopeRect().width()-m_textWidth.width()-1)*(profileWidth-1);

                if (clipX >= 0 && clipX <= profileWidth) {
                    int valX = x-15;
                    if (valX < 0) { valX = 0; }
                    if (valX > scopeRect().width()-55-m_textWidth.width()) { valX = scopeRect().width()-55-m_textWidth.width(); }

                    davinci.drawLine(x, y, x, scopeRect().height()-m_paddingBottom);
                    davinci.drawText(valX, scopeRect().height()-5, QVariant(clipX).toString() + " px");
                }
            }
        }

    }
    davinci.drawText(rightX, scopeRect().height()-m_paddingBottom, "0");
    davinci.drawText(rightX, 10, "255");

    emit signalHUDRenderingFinished(0, 1);
    return hud;
}

QImage Waveform::renderGfxScope(uint accelFactor, const QImage &qimage)
{
    QTime start = QTime::currentTime();
    start.start();

    const int paintmode = ui->paintMode->itemData(ui->paintMode->currentIndex()).toInt();
    WaveformGenerator::Rec rec = m_aRec601->isChecked() ? WaveformGenerator::Rec_601 : WaveformGenerator::Rec_709;
    QImage wave = m_waveformGenerator->calculateWaveform(scopeRect().size() - m_textWidth - QSize(0,m_paddingBottom), qimage,
                                                         (WaveformGenerator::PaintMode) paintmode, true, rec, accelFactor);

    emit signalScopeRenderingFinished(start.elapsed(), 1);
    return wave;
}

QImage Waveform::renderBackground(uint)
{
    emit signalBackgroundRenderingFinished(0, 1);
    return QImage();
}

#include "waveform.moc"
