/*
 * Copyright 2014 Mihai Niculescu <q.quark@gmail.com>
 *
 * This file is part of EqualX Project (https://launchpad.net/equalx/)
 *
 * EqualX 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.
 *
 * EqualX 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 <http://www.gnu.org/licenses/>.
 */

#include <QDebug>
#include <QColorDialog>
#include <QPainter>
#include <QResizeEvent>
#include <QVariant>

#include "ColorChooser.h"

ColorChooser::ColorChooser(QWidget *parent, Qt::WindowFlags f)
    : QFrame(parent, f),
      mFgColor(Qt::black),
      mBgColor(Qt::white),
      mPadding(3),
      mSeparatorWidth(10)
{
    mFgArea.setRect(mPadding, mPadding, 0,0);

    setMinimumSize(80,22);
    setFrameShadow(QFrame::Sunken);
    setFrameShape(QFrame::StyledPanel);

    connect(&mColorsMenu, SIGNAL(triggered(QAction*)), this, SLOT(onColorChosen(QAction*)) );
}

ColorChooser::~ColorChooser()
{
    
}

void ColorChooser::setFgColor(const QString &name)
{
    mFgColor = QColor(name);
}

void ColorChooser::setFgColor(const QColor &color)
{
    mFgColor = color;
}

void ColorChooser::setBgColor(const QString &name)
{
    mBgColor = QColor(name);
}

void ColorChooser::setBgColor(const QColor &color)
{
    mBgColor = color;
}

QSize ColorChooser::sizeHint() const
{
    QSize sh;
    sh = QSize(2*mPadding+mSeparatorWidth+ mFgArea.width()+mBgArea.width(), 2*mPadding+mFgArea.height());

    return sh;
}

void ColorChooser::paintEvent(QPaintEvent * /*event*/)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    QPen pen;
    pen.setWidth(1);
    pen.setColor(Qt::gray);
    pen.setStyle(Qt::SolidLine);

    painter.setPen(pen);

    // draw Foreground color selector
    painter.setBrush(mFgColor);
    painter.drawRect(mFgArea);

    // draw Separator
    painter.setPen(Qt::blue);
    painter.drawLine(mSeparator);

    // draw Background color selector
    painter.setPen(Qt::gray);
    painter.setBrush(mBgColor);
    painter.drawRect(mBgArea);
}

void ColorChooser::resizeEvent(QResizeEvent *event)
{
    int widgetWidth = event->size().width();
    int widgetHeight = event->size().height();

    mSeparatorWidth = widgetWidth/6;

    int w = (int)((widgetWidth-2.0*mPadding-mSeparatorWidth)/2.0);
    int h = (int)(widgetHeight-2.0*mPadding);

    mFgArea.setRect(mPadding, mPadding, w, h);
    mBgArea.setRect(mPadding+w+mSeparatorWidth, mPadding, w,h);


    int x1 = mFgArea.topRight().x()+mSeparatorWidth-2;
    int y1 = mPadding+2;

    int x2 = mFgArea.bottomRight().x()+mPadding+2;
    int y2 = mFgArea.bottomRight().y()-2;

    mSeparator.setLine(x1,y1,x2,y2);
}

void ColorChooser::mousePressEvent(QMouseEvent *event)
{
    if(mFgArea.contains( event->pos()) ) showMenu(CHOICE_FG);

    if(mBgArea.contains( event->pos()) ) showMenu(CHOICE_BG);
}

void ColorChooser::showMenu(ColorChooser::CHOICE chosen)
{
    mSwatch = chosen;

    QPoint popupPoint;
    QString menuTitle;

    switch(chosen){
    case CHOICE_FG:
        qDebug() << "clicked inside FG Area";

        popupPoint =  mapToGlobal( mFgArea.bottomLeft());
        menuTitle = tr("Foreground Color:");
        mActiveColor = mFgColor;
        break;
    case CHOICE_BG:
        qDebug() << "clicked inside BG Area";

        popupPoint =  mapToGlobal( mBgArea.bottomLeft());
        menuTitle = tr("Background Color:");
        mActiveColor = mBgColor;
        break;
    }

    //---------- Setup Colors Menu
    mColorsMenu.clear();

    addMenuAction(Qt::transparent, tr("transparent") );
    addMenuAction(Qt::black, tr("black") );
    addMenuAction(Qt::white, tr("white") );
    addMenuAction(Qt::red, tr("red") );
    addMenuAction(Qt::darkRed, tr("dark red") );
    addMenuAction(Qt::green, tr("green") );
    addMenuAction(Qt::darkGreen, tr("dark green") );
    addMenuAction(Qt::blue, tr("blue") );
    addMenuAction(Qt::darkBlue, tr("dark blue") );
    addMenuAction(Qt::cyan, tr("cyan") );
    addMenuAction(Qt::magenta, tr("magenta") );
    addMenuAction(Qt::yellow, tr("yellow") );
    addMenuAction(Qt::gray, tr("gray") );
    addMenuAction(Qt::darkGray, tr("dark gray") );
    addMenuAction(Qt::lightGray, tr("light gray") );

    mColorsMenu.addSeparator();
    QAction* act = mColorsMenu.addAction(tr("Other Color.."));
    act->setData(mActiveColor);
    connect(act, SIGNAL(triggered()), this, SLOT(showColorsDialog()) );

    // show menu
    mColorsMenu.setWindowTitle(menuTitle);
    mColorsMenu.popup(popupPoint);
}

inline void ColorChooser::addMenuAction(const QColor &fillColor, const QString &name)
{
    QAction* act = mColorsMenu.addAction(createIcon(fillColor), name);
    act->setIconVisibleInMenu(true);
    act->setData(fillColor);
}

inline QIcon ColorChooser::createIcon(const QColor &colorName) const
{
    QPixmap iconPixmap(32,32);
    iconPixmap.fill(QColor(colorName));
    QIcon itemIcon(iconPixmap);
    return itemIcon;
}

void ColorChooser::onColorChosen(QAction *act)
{
    QColor chosenColor = act->data().value<QColor>();

    if(mActiveColor == chosenColor) return;

    switch (mSwatch) {
    case CHOICE_FG:{
        mFgColor = chosenColor;
        emit fgColorChanged(mFgColor);
        break;
    }
    case CHOICE_BG:{
        mBgColor = chosenColor;
        emit bgColorChanged(mBgColor);
        break;
    }
    }

    update();
}

void ColorChooser::showColorsDialog()
{
    switch (mSwatch) {
    case CHOICE_FG:{
        QColor selected  = QColorDialog::getColor(mFgColor);
        if(selected.isValid()) {
            mFgColor = selected;
            emit fgColorChanged(mFgColor);
        }
        break;
    }
    case CHOICE_BG:{
        QColor selected = QColorDialog::getColor(mBgColor);
        if(selected.isValid()) {
            mBgColor = selected;
            emit bgColorChanged(mBgColor);
        }
        break;
    }
    }

    update();
}
