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

 Copyright 2018 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 "MvQEcStyleHelp.h"

#include <QtGlobal>
#include <QApplication>
#include <QComboBox>
#include <QGridLayout>
#include <QLabel>
#include <QLineEdit>
#include <QPainter>
#include <QSortFilterProxyModel>
#include <QToolButton>
#include <QTreeView>
#include <QVBoxLayout>

#include "MvQStyleDb.h"
#include "MvQEcLayerDb.h"
#include "MvQStyleTreeWidget.h"

#include "MvMiscellaneous.h"

#include "HelpFactory.h"

//=====================================================
//
//  MvQEcStyleModel
//
//=====================================================

MvQEcStyleModel::MvQEcStyleModel(QObject* parent) :
    QAbstractItemModel(parent)
{
}

MvQEcStyleModel::~MvQEcStyleModel() = default;

int MvQEcStyleModel::columnCount(const QModelIndex& /*parent */) const
{
    return 1;
}

int MvQEcStyleModel::rowCount(const QModelIndex& parent) const
{
    //Parent is the root:
    if (!parent.isValid()) {
        return MvQStyleDb::instance()->items().count();
    }

    return 0;
}

QVariant MvQEcStyleModel::data(const QModelIndex& index, int role) const
{
    int row = index.row();
    if (row < 0 || row >= MvQStyleDb::instance()->items().count())
        return QVariant();

    if (role == Qt::DisplayRole) {
        return row;
    }
    else if (role == Qt::UserRole) {
        return (isFiltered(row) == true) ? "1" : "0";
    }
    else if (role == SortRole) {
        return MvQStyleDb::instance()->items()[row]->name();
    }

    return QVariant();
}

QVariant MvQEcStyleModel::headerData(const int section, const Qt::Orientation orient, const int role) const
{
    if (orient != Qt::Horizontal || (role != Qt::DisplayRole && role != Qt::ToolTipRole))
        return QAbstractItemModel::headerData(section, orient, role);

    return role == Qt::DisplayRole && section == 0 ? " Styles" : QVariant();
}

QModelIndex MvQEcStyleModel::index(int row, int column, const QModelIndex& parent) const
{
    if (row < 0 || column < 0) {
        return QModelIndex();
    }

    //When parent is the root this index refers to a node or server
    if (!parent.isValid()) {
        return createIndex(row, column);
    }

    return QModelIndex();
}

QModelIndex MvQEcStyleModel::parent(const QModelIndex& /*child*/) const
{
    return QModelIndex();
}

void MvQEcStyleModel::setIndexFilter(QList<int> lst)
{
    indexFilter_ = lst;
}

void MvQEcStyleModel::clearFilter()
{
    indexFilter_.clear();
}

bool MvQEcStyleModel::isFiltered(int row) const
{
    if (!indexFilter_.isEmpty()) {
        if (!indexFilter_.contains(row))
            return false;
    }

    return true;
}

//=====================================================
//
// MvQEcStyleSelectionWidget
//
//=====================================================

MvQEcStyleSelectionWidget::MvQEcStyleSelectionWidget(QWidget* parent) :
    QWidget(parent)
//ignoreFilterChanged_(false)
{
    QVBoxLayout* vb = new QVBoxLayout(this);

    browser_ = new MvQStyleTreeWidget(this);
    vb->addWidget(browser_, 1);

    model_ = new MvQEcStyleModel(this);

    sortModel_ = new QSortFilterProxyModel(this);
#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
    sortModel_->setFilterRegularExpression("1");
#else
    sortModel_->setFilterRegExp("1");
#endif
    sortModel_->setFilterRole(Qt::UserRole);
    sortModel_->setSortRole(MvQEcStyleModel::SortRole);
    sortModel_->setSourceModel(model_);

    //tree_->setSortingEnabled(true);
    //tree_->sortByColumn(1,Qt::AscendingOrder);
    browser_->tree()->setModel(sortModel_);

    connect(browser_->tree()->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)),
            this, SLOT(slotItemSelected(QModelIndex, QModelIndex)));

    //Init the button states!!
    checkButtonState();
}


void MvQEcStyleSelectionWidget::slotItemSelected(const QModelIndex& current, const QModelIndex& /*prev*/)
{
    QModelIndex idxSrc = sortModel_->mapToSource(current);
    if (idxSrc.isValid()) {
        emit itemSelected(idxSrc.row());

        int row = idxSrc.row();
        if (row >= 0 && row < MvQStyleDb::instance()->items().count()) {
            MvQStyleDbItem* item = MvQStyleDb::instance()->items()[row];
            Q_ASSERT(item);
            browser_->setStyle(item);
        }
    }
}


void MvQEcStyleSelectionWidget::slotClearFilter()
{
    //ignoreFilterChanged_=true;
    //nameLe_->clear();
    //keywordCb_->setCurrentIndex(0);
    //colourCb_->setCurrentIndex(0);
    //paramCb_->setCurrentIndex(0);
    //ignoreFilterChanged_=false;

    model_->clearFilter();
    sortModel_->invalidate();
    //checkButtonState();
}

void MvQEcStyleSelectionWidget::checkButtonState()
{
#if 0
    nameResetTb_->setEnabled(!nameLe_->text().isEmpty());
    keywordResetTb_->setEnabled(keywordCb_->currentText() != "ANY");
    colourResetTb_->setEnabled(colourCb_->currentText() != "ANY");
    paramResetTb_->setEnabled(paramCb_->currentText() != "ANY");

    resetTb_->setEnabled(keywordResetTb_->isEnabled() ||
                         nameResetTb_->isEnabled() || colourResetTb_->isEnabled() ||
                         paramResetTb_->isEnabled());
#endif
}

void MvQEcStyleSelectionWidget::setCurrent(const std::string& name, const std::string& layerName)
{
    if (layerName_ != layerName)
        layerName_ = layerName;
    else {
        QModelIndex idxSrc = sortModel_->mapToSource(browser_->tree()->currentIndex());
        if (idxSrc.isValid()) {
            int row = idxSrc.row();
            if (row >= 0 && row < MvQStyleDb::instance()->items().size() &&
                MvQStyleDb::instance()->items()[row]->name().toStdString() == name)
                return;
        }
    }

    slotClearFilter();
    int row = MvQStyleDb::instance()->indexOf(name);

    if (MvQEcLayerDbItem* layerItem = MvQEcLayerDb::instance()->find(layerName_)) {
        model_->setIndexFilter(layerItem->styleIds());
        sortModel_->invalidate();
    }

    if (row >= 0) {
        QModelIndex idxSrc = model_->index(row, 0);
        if (idxSrc.isValid()) {
            browser_->tree()->setCurrentIndex(sortModel_->mapFromSource(idxSrc));

            int row = idxSrc.row();
            emit itemSelected(row);

            if (row >= 0 && row < MvQStyleDb::instance()->items().count()) {
                MvQStyleDbItem* item = MvQStyleDb::instance()->items()[row];
                Q_ASSERT(item);
                browser_->setStyle(item);
            }
        }
    }
}

//==================================================
//
//  MvQEcStyleHelp
//
//==================================================

MvQEcStyleHelp::MvQEcStyleHelp(RequestPanel& owner, const MvIconParameter& param) :
    MvQRequestPanelHelp(owner, param)
{
    selector_ = new MvQEcStyleSelectionWidget(parentWidget_);

    connect(selector_, SIGNAL(itemSelected(int)),
            this, SLOT(slotSelected(int)));
}

void MvQEcStyleHelp::slotSelected(int idx)
{
    if (idx >= 0 && idx < MvQStyleDb::instance()->items().count()) {
        if (MvQStyleDb::instance()->items()[idx]->name() != oriName_) {
            std::vector<std::string> vs;
            vs.push_back(std::to_string(idx));
            emit edited(vs);
            oriName_.clear();
        }
    }
}

void MvQEcStyleHelp::refresh(const std::vector<std::string>& values)
{
    if (values.size() == 0)
        return;

    oriName_ = QString::fromStdString(values[0]);

    std::string layerName;
    if (values.size() >= 2)
        layerName = values[1];

    selector_->setCurrent(values[0], layerName);
}

static HelpMaker<MvQEcStyleHelp> maker2("help_ecstyle");
