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

 Copyright 2012 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 "MvQMethods.h"

#include <QtGlobal>
#include <QApplication>
#include <QGuiApplication>
#include <QClipboard>

#include <QAbstractButton>
#include <QAbstractItemModel>
#include <QAction>
#include <QButtonGroup>
#include <QComboBox>
#include <QDebug>
#include <QFile>
#include <QFontMetrics>
#include <QLabel>
#include <QLineEdit>
#include <QStackedWidget>
#include <QTabBar>
#include <QTabWidget>
#include <QTreeView>
#include <QOpenGLContext>

#include "MvMiscelaneous.h"

static QColor shortCutCol(46,65,107);

namespace MvQ
{
void initComboBox(QSettings& settings, QString key, QComboBox* cb)
{
    Q_ASSERT(cb);
    QString txt = settings.value(key).toString();
    for (int i = 0; i < cb->count(); i++) {
        if (cb->itemText(i) == txt) {
            cb->setCurrentIndex(i);
            return;
        }
    }

    if (cb->currentIndex() == -1)
        cb->setCurrentIndex(0);
}

void initTabId(QSettings& settings, QString key, QTabWidget* tab)
{
    Q_ASSERT(tab);

    QString s = settings.value(key).toString();
    for (int i = 0; i < tab->count(); i++) {
        if (tab->tabBar()->tabData(i).toString() == s) {
            tab->setCurrentIndex(i);
            return;
        }
    }
}

void saveTabId(QSettings& settings, QString key, QTabWidget* tab)
{
    Q_ASSERT(tab);

    int idx = tab->currentIndex();
    if (idx >= 0) {
        settings.setValue(key, tab->tabBar()->tabData(idx).toString());
    }
}

void initTreeColumnWidth(QSettings& settings, QString key, QTreeView* tree)
{
    Q_ASSERT(tree);

    QStringList dataColumns = settings.value(key).toStringList();
    for (int i = 0; i < tree->model()->columnCount() - 1 && i < dataColumns.size(); i++) {
        tree->setColumnWidth(i, dataColumns[i].toInt());
    }
}

void saveTreeColumnWidth(QSettings& settings, QString key, QTreeView* tree)
{
    QStringList dataColumns;
    for (int i = 0; i < tree->model()->columnCount() - 1; i++) {
        dataColumns << QString::number(tree->columnWidth(i));
    }
    settings.setValue(key, dataColumns);
}


void initStacked(QSettings& settings, QString key, QStackedWidget* stacked)
{
    Q_ASSERT(stacked);

    int v = settings.value(key).toInt();
    if (v >= 0 && v < stacked->count())
        stacked->setCurrentIndex(v);
}

void initButtonGroup(QSettings& settings, QString key, QButtonGroup* bg)
{
    Q_ASSERT(bg);

    int v = settings.value(key).toInt();
    if (v >= 0 && v < bg->buttons().count()) {
        bg->buttons().at(v)->setChecked(true);
        bg->buttons().at(v)->click();
    }
}

void initCheckableAction(QSettings& settings, QString key, QAction* ac)
{
    Q_ASSERT(ac);

    if (settings.contains(key)) {
        ac->setChecked(settings.value(key).toBool());
    }
}


void showTabLabel(QTabWidget* tab, int index, QPixmap pix)
{
    Q_ASSERT(tab);
    QWidget* w    = tab->tabBar()->tabButton(index, QTabBar::RightSide);
    QLabel* label = 0;
    if (w) {
        //qDebug() << QString(w->metaObject()->className());
        Q_ASSERT(QString(w->metaObject()->className()) == "QLabel");
    }
    else {
        label = new QLabel(tab);
        label->setPixmap(pix);
        tab->tabBar()->setTabButton(index, QTabBar::RightSide, label);
    }
}

void hideTabLabel(QTabWidget* tab, int index)
{
    Q_ASSERT(tab);
    QWidget* w = tab->tabBar()->tabButton(index, QTabBar::RightSide);
    if (w) {
        Q_ASSERT(QString(w->metaObject()->className()) == "QLabel");
        tab->tabBar()->setTabButton(index, QTabBar::RightSide, 0);
        delete w;
    }
}

QString formatBoldText(QString txt, QColor col)
{
    return "<b><font color=\'" + col.name() + "\'>" + txt + "</font></b>";
}

QString formatText(QString txt, QColor col)
{
    return "<font color=\'" + col.name() + "\'>" + txt + "</font>";
}

QString formatTableThText(QString txt, QColor col)
{
    return "<th><font color=\'" + col.name() + "\'>" + txt + "</font></th>";
}

QString formatTableTrBg(QString txt, QColor col)
{
    return "<tr bgcolor=\'" + col.name() + "\'>" + txt + "</tr>";
}

QString formatTableTdText(QString txt, QColor col)
{
    return "<td><font color=\'" + col.name() + "\'>" + txt + "</font></td>";
}

QString formatTableTdBg(QString txt, QColor col)
{
    return "<td bgcolor=\'" + col.name() + "\'>" + txt + "</td>";
}

QString formatTableRow(QString col1Text, QString col2Text, QColor bg, QColor fg, bool boldCol1)
{
    QString txt;
    if (boldCol1)
        txt = "<td>" + formatBoldText(col1Text, fg) + "</td>";
    else
        txt = formatTableTdText(col1Text, fg);

    txt += formatTableTdText(col2Text, fg);

    return formatTableTrBg(txt, bg);
}

void toClipboard(QString txt)
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
    QClipboard* cb = QGuiApplication::clipboard();
    cb->setText(txt, QClipboard::Clipboard);
    cb->setText(txt, QClipboard::Selection);
#else
    QClipboard* cb = QApplication::clipboard();
    cb->setText(txt, QClipboard::Clipboard);
    cb->setText(txt, QClipboard::Selection);
#endif
}

QString fromClipboard()
{
    return QGuiApplication::clipboard()->text();
}


void initSettings(QString path)
{
#ifdef __APPLE__
    QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, path);
#else
    QSettings::setPath(QSettings::NativeFormat, QSettings::UserScope, path);
#endif
}

QString iconPixmapPath(QString name)
{
    QString svg = QString::fromStdString(metview::iconDirFile(name.toStdString() + ".svg"));

    QFile f(svg);
    if (f.exists()) {
        return svg;
    }
    else {
        QString xpm = QString::fromStdString(metview::iconDirFile(name.toStdString() + ".xpm"));
        QFile fxpm(xpm);
        if (fxpm.exists()) {
            return xpm;
        }
    }

    return {};
}

void setLineEditTextFormat(QLineEdit* lineEdit, const QList<QTextLayout::FormatRange>& formats)
{
    if(!lineEdit)
        return;

    QList<QInputMethodEvent::Attribute> attributes;
    foreach(const QTextLayout::FormatRange& fr, formats)
    {
        QInputMethodEvent::AttributeType type = QInputMethodEvent::TextFormat;
        int start = fr.start - lineEdit->cursorPosition();
        int length = fr.length;
        QVariant value = fr.format;
        attributes.append(QInputMethodEvent::Attribute(type, start, length, value));
    }
    QInputMethodEvent event(QString(), attributes);
    QCoreApplication::sendEvent(lineEdit, &event);
}

void clearLineEditTextFormat(QLineEdit* lineEdit)
{
    setLineEditTextFormat(lineEdit, QList<QTextLayout::FormatRange>());
}

bool hasOpenGLSupport()
{
    QOpenGLContext *current = QOpenGLContext::currentContext();
    if (current && current->isValid())
        return true;

    QOpenGLContext ctx;
    return (ctx.create() == true);
}

void changeFontSize(QWidget* w, int delta)
{
    QFont f = w->font();
    int fs = f.pointSize();

    if(delta > 0) {
        if(fs >= 100)
            return;

        if (fs+delta > 100)
            fs = 100;

        f.setPointSize(fs+delta);
        w->setFont(f);
    } else if(delta < 0) {
        if(fs <= 6)
            return;

        if (fs+delta < 6)
            fs = 6;

        f.setPointSize(fs+delta);
        w->setFont(f);
    }
}

void setFontSize(QWidget* w, int fsNew)
{
    QFont f = w->font();
    int fs = f.pointSize();

    if (fsNew <=0)
        return;

    if (fsNew < 6)
        fsNew = 6;

    if (fsNew > 100)
        fsNew = 100;

    if (fs == fsNew)
        return;

    f.setPointSize(fsNew);
    w->setFont(f);
}

void showShortcutInContextMenu(QWidget* w)
{
    QList<QAction*> lst = w->findChildren<QAction*>();
    showShortcutInContextMenu(lst);
}

void showShortcutInContextMenu(QList<QAction*> lst)
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
    foreach(QAction* ac, lst) {
        ac->setShortcutVisibleInContextMenu(true);
    }
#endif
}

QString formatShortCut(QString text)
{
    return "<code><font color=\'" + shortCutCol.name() + "\'>" + text + "</font></code>";
}

QString formatShortCut(QAction* ac)
{
    Q_ASSERT(ac);

    return "<code><font color=\'" + shortCutCol.name() + "\'>&nbsp;(" +
        ac->shortcut().toString() + ")</font></code>";
}

void addShortCutToToolTip(QWidget* w)
{
    QList<QAction*> lst = w->findChildren<QAction*>();
    addShortCutToToolTip(lst);
}

void addShortCutToToolTip(QList<QAction*> alst)
{
    Q_FOREACH(QAction *ac,alst)
    {
        if(!ac->shortcut().isEmpty())
        {
            QString tt=ac->toolTip();
            if(!tt.isEmpty())
            {
                tt+=" " + formatShortCut(ac);
                ac->setToolTip(tt);
            }
        }
    }
}

int textWidth(const QFontMetrics& fm, QString txt, int len)
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
    return fm.horizontalAdvance(txt, len);
#else
    return fm.width(txt, len);
#endif
}

int textWidth(const QFontMetrics& fm, QChar ch)
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
    return fm.horizontalAdvance(ch);
#else
    return fm.width(ch);
#endif
}

}  //namespace MvQ
