/***************************** LICENSE START ***********************************

 Copyright 2014 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#include "MvQColourLine.h"

#include <QAction>
#include <QComboBox>
#include <QDebug>
#include <QPainter>

#include "MvQMethods.h"
#include "MvQPalette.h"
#include "MvQRequestPanelHelp.h"

#include "LineFactory.h"
#include "RequestPanel.h"

MvQColourLine::MvQColourLine(RequestPanel& owner, const MvIconParameter& param) :
    MvQRequestPanelLine(owner, param),
    customColIndex_(-1)
{
    colCb_ = new QComboBox(parentWidget_);

    QFont font;
    QFontMetrics fm(font);
    int h = fm.height() + 4;
    int w = h * 2;
    colCb_->setIconSize(QSize(w, h));

    param_.scan(*this);

    // The custom colour (if exists) is always the last one
    customColIndex_ = colCb_->count();

    owner_.addWidget(colCb_, row_, WidgetColumn);

    connect(colCb_, SIGNAL(currentIndexChanged(int)),
            this, SLOT(slotCurrentChanged(int)));

    //----------------------------------
    // Context menu
    //-----------------------------------
    colCb_->setContextMenuPolicy(Qt::ActionsContextMenu);

    auto* acCopyCol = new QAction(this);
    acCopyCol->setText(tr("&Copy colour"));
    acCopyCol->setShortcut(QKeySequence(tr("Ctrl+C")));
    // acCopyCol->setIcon(QPixmap(":/desktop/editcopy.svg"));
    colCb_->addAction(acCopyCol);

    connect(acCopyCol, SIGNAL(triggered()),
            this, SLOT(slotCopyColour()));

#if 0
    QAction *acCopyRgb=new QAction(this);
    acCopyRgb->setText(tr("Copy colour as &RGB"));
    colCb_->addAction(acCopyRgb);

    connect(acCopyRgb,SIGNAL(triggered()),
            this,SLOT(slotCopyRgb()));

    QAction *acCopyHsl=new QAction(this);
    acCopyHsl->setText(tr("Copy colour as &HSL"));
    colCb_->addAction(acCopyHsl);

    connect(acCopyHsl,SIGNAL(triggered()),
            this,SLOT(slotCopyHsl()));

    QAction *sep=new QAction(this);
    sep->setSeparator(true);
    colCb_->addAction(sep);
#endif

    auto* acPasteCol = new QAction(this);
    acPasteCol->setText(tr("&Paste colour"));
    acPasteCol->setShortcut(QKeySequence(tr("Ctrl+V")));
    // acPasteCol->setIcon(QPixmap(":/desktop/editpaste.svg"));
    colCb_->addAction(acPasteCol);

    connect(acPasteCol, SIGNAL(triggered()),
            this, SLOT(slotPasteColour()));
}

void MvQColourLine::next(const MvIconParameter&, const char* first, const char* /*second*/)
{
    addColour(MvQPalette::magics(first), QString::fromStdString(param_.beautifiedName(first)), QString(first));
}

void MvQColourLine::setColour(int idx, QColor col)
{
    if (idx < 0 || idx > colCb_->count() - 1)
        return;

    QIcon icon;

    if (pix_.isNull()) {
        int w = colCb_->iconSize().width();
        int h = colCb_->iconSize().height();
        pix_ = QPixmap(w, h);
        pix_.fill(Qt::transparent);
    }

    QPainter painter(&pix_);

    if (col.isValid()) {
        // paint the chequered background when alpha is set
        if (col.alpha() != 255) {
            MvQPalette::paintAlphaBg(&painter, QRect(0, 0, pix_.width(), pix_.height()));
#if 0
            QColor c1(170,170,170);
            QColor c2(190,190,190);
            int rs=10;
            int nx=pix_.width()/rs;
            int ny=pix_.height()/rs;
            QColor cAct=c1;
            for(int i=0; i <= nx; i++)
                for(int j=0; j <= ny; j++)
            {
                QRect r(1+i*rs,1+j*rs,rs,rs);
                if(j%2 ==0)
                {
                    if(i%2 == 0) cAct=c1;
                    else cAct=c2;
                }
                else
                {
                    if(i%2 == 0) cAct=c2;
                    else cAct=c1;
                }
                painter.fillRect(r,cAct);
            }
#endif
            painter.setPen(QColor(0, 0, 0, col.alpha()));
        }
        else {
            painter.setPen(Qt::black);
        }

        painter.setBrush(QBrush(col));
        painter.drawRect(1, 1, pix_.width() - 2, pix_.height() - 2);
    }
    else {
        pix_.fill(Qt::transparent);
        // painter.setBrush(Qt::white);
        painter.setPen(QPen(Qt::gray, 0., Qt::DashLine));
        painter.drawRect(1, 1, pix_.width() - 2, pix_.height() - 3);
    }

    icon.addPixmap(pix_);

    colCb_->setItemIcon(idx, icon);
}

// it should only be called during the initial scan
void MvQColourLine::addColour(QColor color, QString name, QString realName, bool setCurrent)
{
    bool pseudoCol = MvQPalette::isPseudo(realName.toStdString());

    if (!color.isValid() && !pseudoCol)
        return;

    for (int i = 0; i < colCb_->count(); i++) {
        if (name.compare(colCb_->itemText(i), Qt::CaseInsensitive) == 0) {
            if (setCurrent) {
                colCb_->setCurrentIndex(i);
            }
            return;
        }
    }

    int idx = -1;
    if (colCb_->count() == 0) {
        colCb_->addItem(name, realName);
        idx = 0;
    }
    else {
        int i = 0;
        while (i < colCb_->count() && colCb_->itemText(i) < name)
            i++;

        idx = i;
        colCb_->insertItem(idx, name, realName);
        if (setCurrent)
            colCb_->setCurrentIndex(idx);
    }

    if (idx != -1) {
        setColour(idx, color);
    }
}

// There can be only one custom colour - this is always the last one in the list
void MvQColourLine::setCustomColour(QColor color, QString name, QString realName, bool setCurrent)
{
    if (!color.isValid())
        return;

    if (colCb_->count() != customColIndex_ + 1) {
        Q_ASSERT(colCb_->count() == customColIndex_);
        colCb_->insertItem(customColIndex_, name, realName);
    }
    else {
        colCb_->setItemText(customColIndex_, name);
        colCb_->setItemData(customColIndex_, realName);
    }
    setColour(customColIndex_, color);

    if (setCurrent) {
        colCb_->setCurrentIndex(customColIndex_);
        // although we set the current index, this does not always trigger
        // slotCurrentChanged because all custom RGB values will have the
        // same index (42), even though they might be different colours
        // (which could be an issue if we open two different icons which both
        // have custom colours for the same parameter).
        // Therefore we manually trigger slotCurrentChanged here to make sure
        slotCurrentChanged(customColIndex_);
    }
}

void MvQColourLine::refresh(const std::vector<std::string>& values)
{
    if (values.size() > 0) {
        for (int i = 0; i < colCb_->count(); i++) {
            if (colCb_->itemData(i).toString().toStdString() == values[0]) {
                colCb_->setCurrentIndex(i);
                return;
            }
        }

        QString name = QString::fromStdString(values[0]);
        // This sets the current index as well
        setCustomColour(MvQPalette::magics(values[0]), name, name, true);
    }

    // changed_ = false;
}

void MvQColourLine::slotCurrentChanged(int index)
{
    if (index >= 0 && index < colCb_->count()) {
        QString name = colCb_->itemData(index).toString();
        owner_.set(param_.name(), name.toStdString());
        if (!MvQPalette::isPseudo(name.toStdString())) {
            if (helper_ && helper_->widget())
                helper_->widget()->setEnabled(true);
            updateHelper();
        }
        else {
            if (helper_ && helper_->widget())
                helper_->widget()->setEnabled(false);
        }
    }
}

void MvQColourLine::slotHelperEdited(const std::vector<std::string>& values)
{
    if (values.size() > 0) {
        for (int i = 0; i < colCb_->count(); i++) {
            if (colCb_->itemData(i).toString().toStdString() == values[0]) {
                colCb_->setCurrentIndex(i);
                return;
            }
        }

        QString name = QString::fromStdString(values[0]);
        // This sets the current index as well
        setCustomColour(MvQPalette::magics(values[0]), name, name, true);

        // If the current index did not change the slotCurrentChanged() was
        // not called, so here we need to notify the owner about the change!!
        // if(colCb_->currentIndex() ==  currentPrev)
        //{
        //	owner_.set(param_.name(),name.toStdString());
        // }
    }
}

void MvQColourLine::updateHelper()
{
    if (!helper_)
        return;

    int index = colCb_->currentIndex();

    std::vector<std::string> vals;
    vals.push_back(colCb_->itemData(index).toString().toStdString());
    helper_->refresh(vals);
}

void MvQColourLine::slotHelperEditConfirmed()
{
    int index = colCb_->currentIndex();
    if (index != -1) {
        QString name = colCb_->itemData(index).toString();
        owner_.set(param_.name(), name.toStdString());
    }
}

void MvQColourLine::slotCopyColour()
{
    int index = colCb_->currentIndex();
    if (index != -1) {
        QString name = colCb_->itemData(index).toString();
        QColor col = MvQPalette::magics(name.toStdString());
        MvQ::toClipboard("\"" + QString::fromStdString(MvQPalette::toString(col)) + "\"");
    }
}

void MvQColourLine::slotCopyRgb()
{
    int index = colCb_->currentIndex();
    if (index != -1) {
        QString name = colCb_->itemData(index).toString();
        QColor col = MvQPalette::magics(name.toStdString());
        MvQ::toClipboard(MvQPalette::toRgbString(col));
    }
}

void MvQColourLine::slotCopyHsl()
{
    int index = colCb_->currentIndex();
    if (index != -1) {
        QString name = colCb_->itemData(index).toString();
        QColor col = MvQPalette::magics(name.toStdString());
        MvQ::toClipboard(MvQPalette::toHslString(col));
    }
}

void MvQColourLine::slotPasteColour()
{
    QString txt = MvQ::fromClipboard();
    if (!txt.isEmpty()) {
        QColor col = MvQPalette::magics(txt.toStdString());
        if (col.isValid()) {
            std::vector<std::string> values;
            values.push_back(MvQPalette::toString(col));
            slotHelperEdited(values);
        }
    }
}


static LineMaker<MvQColourLine> maker1("colour");
