/*****************************************************************************
 *
 * Testmanager - Graphical Automation and Visualisation Tool
 *
 * Copyright (C) 2018 - 2019  Florian Pose <fp@igh.de>
 *
 * This file is part of Testmanager.
 *
 * Testmanager 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.
 *
 * Testmanager 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 Testmanager. If not, see <http://www.gnu.org/licenses/>.
 *
 ****************************************************************************/

#include "DialPluginDialog.h"

#include <QAbstractTableModel>

#include <algorithm> // std::sort()

/****************************************************************************/

class DialPluginDialog::Model:
    public QAbstractTableModel
{
    public:
        Model(QGradientStops *stops):
            stops(stops)
        {
            std::sort(stops->begin(), stops->end(),
                    [](const QGradientStop &a, const QGradientStop &b)
                    {
                      return a.first < b.first;
                    });
        }

        /********************************************************************/

        int rowCount(const QModelIndex &index) const
        {
            if (index.isValid()) {
                return 0;
            }
            else {
                return stops->size();
            }
        }

        /********************************************************************/

        int columnCount(const QModelIndex &) const
        {
            return 2;
        }

        /********************************************************************/

        QVariant data(const QModelIndex &index, int role) const
        {
            if (not index.isValid() or
                    index.row() < 0 or index.row() >= stops->size()) {
                return QVariant();
            }

            switch (index.column()) {

                case 0: // value
                    switch (role) {
                        case Qt::DisplayRole:
                        case Qt::EditRole:
                            return stops->at(index.row()).first;
                        default:
                            return QVariant();
                    }
                    break;

                case 1: // color
                    switch (role) {
                        case Qt::DisplayRole:
                            return stops->at(
                                    index.row()).second.name(QColor::HexArgb);
                        case Qt::EditRole:
                            return stops->at(index.row()).second.rgba();
                        case Qt::DecorationRole:
                            return stops->at(index.row()).second;
                        default:
                            return QVariant();
                    }
                    break;

                default:
                    return QVariant();
            }
        }

        /********************************************************************/

        bool setData(const QModelIndex &index, const QVariant &value,
                int role)
        {
            if (role != Qt::EditRole or not index.isValid() or
                    index.row() < 0 or index.row() >= stops->size() or
                    index.column() < 0 or index.column() >= 2) {
                return false;
            }

            switch (index.column()) {

                case 0: // value
                    (*stops)[index.row()].first = value.toDouble();
                    return true;

                case 1: // color
                    {
                        QColor c(QColor().fromRgba(value.toInt()));
                        if (c.isValid()) {
                            (*stops)[index.row()].second = c;
                            return true;
                        }
                    }
                    return false;
            }

            return false;
        }

        /********************************************************************/

        QVariant headerData(int section, Qt::Orientation o, int role) const
        {
            if (role == Qt::DisplayRole && o == Qt::Horizontal) {
                switch (section) {
                    case 0:
                        return DialPluginDialog::tr("Value");

                    case 1:
                        return DialPluginDialog::tr("Color");

                    default:
                        return QVariant();
                }
            }
            else {
                return QVariant();
            }
        }

        /********************************************************************/

        Qt::ItemFlags flags(const QModelIndex &index) const
        {
            if (!index.isValid()) {
                return Qt::NoItemFlags;
            }

            return Qt::ItemIsEnabled | Qt::ItemIsEditable |
                Qt::ItemIsSelectable;
        }

        /********************************************************************/

        void addRow()
        {
            beginInsertRows(QModelIndex(), stops->size(), stops->size());
            stops->append(QGradientStop(0.0, QColor()));
            endInsertRows();
        }

        /********************************************************************/

        void remove(const QModelIndexList &indexes)
        {
            QList<QPersistentModelIndex> persistentIndexes;

            foreach (QModelIndex index, indexes) {
                persistentIndexes << index;
            }

            foreach (const QPersistentModelIndex &index, persistentIndexes) {
                if (index.isValid()) {
                    beginRemoveRows(QModelIndex(), index.row(), index.row());
                    stops->removeAt(index.row());
                    endRemoveRows();
                }
            }
        }

        /********************************************************************/

    private:
        QGradientStops * const stops;
};

/****************************************************************************/

DialPluginDialog::DialPluginDialog(QGradientStops *stops, QWidget *parent):
    QDialog(parent),
    stops(stops),
    model(new Model(stops)),
    colorDelegate(this)
{
    setupUi(this);

    tableView->setItemDelegateForColumn(1, &colorDelegate);
    tableView->setModel(model);

    connect(tableView->selectionModel(),
            SIGNAL(selectionChanged(const QItemSelection &,
                    const QItemSelection &)),
            this, SLOT(selectionChanged(const QItemSelection &,
                    const QItemSelection &)));
}

/****************************************************************************/

DialPluginDialog::~DialPluginDialog()
{
    tableView->setModel(nullptr);
    delete model;
}

/****************************************************************************/

void DialPluginDialog::on_buttonBox_accepted()
{
    accept();
}

/****************************************************************************/

void DialPluginDialog::on_toolButtonAdd_clicked()
{
    model->addRow();
}

/****************************************************************************/

void DialPluginDialog::on_toolButtonRemove_clicked()
{
    model->remove(tableView->selectionModel()->selectedIndexes());
}

/****************************************************************************/

void DialPluginDialog::selectionChanged(const QItemSelection &,
        const QItemSelection &)
{
    toolButtonRemove->setEnabled(tableView->selectionModel()->hasSelection());
}

/****************************************************************************/
