/***************************** 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 "MvQTheme.h"

#include <QApplication>
#include <QColor>
#include <QDebug>
#include <QFile>
#include <QLinearGradient>

#include "MvRequest.h"

static QHash<QString, QPalette::ColorRole> paletteId;
QHash<QString, QHash<QString, QBrush> > MvQTheme::groups_;

MvQTheme::MvQTheme()
{
    if (paletteId.isEmpty()) {
        paletteId["window"]          = QPalette::Window;
        paletteId["windowtext"]      = QPalette::WindowText;
        paletteId["base"]            = QPalette::Base;
        paletteId["alternatebase"]   = QPalette::AlternateBase;
        paletteId["tooltipbase"]     = QPalette::ToolTipBase;
        paletteId["tooltiptext"]     = QPalette::ToolTipText;
        paletteId["text"]            = QPalette::Text;
        paletteId["button"]          = QPalette::Button;
        paletteId["buttontext"]      = QPalette::ButtonText;
        paletteId["brighttext"]      = QPalette::BrightText;
        paletteId["light"]           = QPalette::Light;
        paletteId["midlight"]        = QPalette::Midlight;
        paletteId["dark"]            = QPalette::Dark;
        paletteId["mid"]             = QPalette::Mid;
        paletteId["shadow"]          = QPalette::Shadow;
        paletteId["higlight"]        = QPalette::Highlight;
        paletteId["highlightedtext"] = QPalette::HighlightedText;
        paletteId["link"]            = QPalette::Link;
        paletteId["linkvisited"]     = QPalette::LinkVisited;
    }
}

void MvQTheme::load(QApplication* app, QString id)
{
    /*QHashIterator<QString,QPalette::ColorRole> it(paletteId);
 	while (it.hasNext()) 
	{
     		it.next();
		QColor c=app->palette().color(QPalette::Disabled,it.value());
		qDebug() << it.key() << c.red() << c.green() << c.blue();
	}*/

    groups_.clear();

    if (const char* dshare = getenv("METVIEW_DIR_SHARE")) {
        MvRequest r;

        string p(dshare);
        p += "/app-defaults/UiTheme." + id.toStdString();
        r.read(p.c_str());
        if (r) {
            palette_ = app->palette();

            do
                parse(r);
            while (r.advance());

            app->setPalette(palette_);
        }

        QString stylePath(dshare);
        stylePath += "/app-defaults/" + id + ".qss";
        QFile file(stylePath);
        if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
            return;

        QString styleStr(file.readAll());
        app->setStyleSheet(styleStr);
    }
}

void MvQTheme::parse(const MvRequest& r)
{
    const char* verb = r.getVerb();
    if (!verb)
        return;

    if (strcmp(verb, "palette_active") == 0) {
        readPalette(QPalette::Active, r);
    }
    else if (strcmp(verb, "palette_disabled") == 0) {
        readPalette(QPalette::Disabled, r);
    }
    else if (strcmp(verb, "palette_inactive") == 0) {
        readPalette(QPalette::Inactive, r);
    }
    else {
        readGroup(verb, r);
    }
}

void MvQTheme::readPalette(QPalette::ColorGroup group, const MvRequest& r)
{
    QHashIterator<QString, QPalette::ColorRole> it(paletteId);
    while (it.hasNext()) {
        it.next();
        if (const char* c = r(it.key().toStdString().c_str())) {
            QString val(c);
            if (val.startsWith("rgb"))
                palette_.setColor(group, it.value(), colour(val));
            else if (val.startsWith("gradient")) {
                palette_.setBrush(group, it.value(), brush(val));
            }
        }
    }
}

void MvQTheme::readGroup(const char* verb, const MvRequest& r)
{
    QHash<QString, QBrush> item;

    int n = r.countParameters();

    for (int i = 0; i < n; i++) {
        if (const char* par = r.getParameter(i)) {
            if (const char* c = r(par)) {
                QString val(c);
                item[QString(par)] = brush(val);
            }
        }
    }

    if (!item.isEmpty())
        groups_[QString(verb)] = item;
}

QColor MvQTheme::colour(QString name)
{
    QColor col;
    QRegExp rx("rgb\\((\\d+),(\\d+),(\\d+),?(\\d+)?");

    if (rx.indexIn(name) > -1) {
        if (rx.captureCount() >= 3) {
            col = QColor(rx.cap(1).toInt(),
                         rx.cap(2).toInt(),
                         rx.cap(3).toInt(),
                         rx.cap(4).isEmpty() ? 255 : rx.cap(4).toInt());
        }
    }
    return col;
}

QBrush MvQTheme::brush(QString name)
{
    if (name.startsWith("rgb"))
        return QBrush(colour(name));

    QColor col1, col2;
    float x1, y1, x2, y2;

    QRegExp rx("p1\\((\\d+),(\\d+)");
    if (rx.indexIn(name) > -1 && rx.captureCount() == 2) {
        x1 = rx.cap(1).toFloat();
        y1 = rx.cap(2).toFloat();
    }
    else
        return QBrush();

    rx = QRegExp("p2\\((\\d+),(\\d+)");
    if (rx.indexIn(name) > -1 && rx.captureCount() == 2) {
        x2 = rx.cap(1).toFloat();
        y2 = rx.cap(2).toFloat();
    }
    else
        return QBrush();

    rx = QRegExp("rgb\\((\\d+),(\\d+),(\\d+),?(\\d+)?\\),rgb\\((\\d+),(\\d+),(\\d+),?(\\d+)?");
    if (rx.indexIn(name) > -1 && rx.captureCount() == 8) {
        col1 = QColor(rx.cap(1).toInt(),
                      rx.cap(2).toInt(),
                      rx.cap(3).toInt(),
                      rx.cap(4).isEmpty() ? 255 : rx.cap(4).toInt());

        col2 = QColor(rx.cap(5).toInt(),
                      rx.cap(6).toInt(),
                      rx.cap(7).toInt(),
                      rx.cap(8).isEmpty() ? 255 : rx.cap(8).toInt());
    }
    else
        return QBrush();

    QLinearGradient grad;

    grad.setCoordinateMode(QGradient::ObjectBoundingMode);
    grad.setStart(x1, y1);
    grad.setFinalStop(x2, y2);
    grad.setColorAt(0, col1);
    grad.setColorAt(1, col2);

    return QBrush(grad);
}

QBrush MvQTheme::brush(QString group, QString item)
{
    QHash<QString, QHash<QString, QBrush> >::const_iterator it = groups_.find(group);
    if (it != groups_.end()) {
        QHash<QString, QBrush>::const_iterator itC = it.value().find(item);
        if (itC != it.value().end())
            return itC.value();
    }


    return QColor();
}


QColor MvQTheme::colour(QString group, QString item)
{
    return brush(group, item).color();
}
