/***************************** 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 <QButtonGroup>
#include <QDebug>
#include <QLabel>
#include <QListWidget>
#include <QHBoxLayout>
#include <QPainter>
#include <QStackedLayout>
#include <QToolButton>
#include <QVBoxLayout>

#include "MgQSceneItem.h"

#include "MvQDataWidget.h"
#include "MvQLayerDataWidget.h"
#include "MvQLayerMetaDataWidget.h"

MvQDataWidget::MvQDataWidget(MgQPlotScene* scene, MvQPlotView* plotView, QWidget* parent) :
    QWidget(parent),
    sceneItem_(0)
{
    metaLoaded_ = false;
    dataLoaded_ = false;

    QVBoxLayout* layout = new QVBoxLayout;
    layout->setContentsMargins(2, 2, 2, 2);
    setLayout(layout);

    //----------------------
    // Layer selector list
    //----------------------

    QHBoxLayout* hb = new QHBoxLayout;
    layout->addLayout(hb);

    layerList_ = new QListWidget;
    layerList_->setViewMode(QListView::IconMode);
    layerList_->setFlow(QListView::LeftToRight);
    layerList_->setMovement(QListView::Static);
    layerList_->setWrapping(false);
    layerList_->setIconSize(QSize(48, 48));
    layerList_->setMaximumHeight(75);
    layerList_->setSpacing(5);
    hb->addWidget(layerList_);

    connect(layerList_, SIGNAL(itemActivated(QListWidgetItem*)),
            this, SLOT(slotSelectLayerFromList(QListWidgetItem*)));


    //Top row
    hb = new QHBoxLayout;
    hb->setContentsMargins(0, 0, 0, 0);
    layout->addLayout(hb);

    //connect(showLayerTb_,SIGNAL(toggled(bool)),
    //	this,SLOT(slotLayerMeta(bool)));

    showMetaTb_ = new QToolButton(this);
    showMetaTb_->setText(tr("Metadata"));
    showMetaTb_->setToolTip(tr("View metadata"));
    //showMetaTb_->setIcon(QPixmap(QString::fromUtf8(":/uPlot/meta_data.svg")));
    showMetaTb_->setCheckable(true);
    showMetaTb_->setChecked(false);
    //showMetaTb_->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);

    hb->addWidget(showMetaTb_);
    //hb->addStretch(1);

    //connect(showLayerTb_,SIGNAL(toggled(bool)),
    //	this,SLOT(slotLayerMeta(bool)));

    showDataTb_ = new QToolButton(this);
    showDataTb_->setText(tr("Values"));
    showDataTb_->setToolTip(tr("View values"));
    //showDataTb_->setIcon(QPixmap(QString::fromUtf8(":/uPlot/meta_data.svg")));
    showDataTb_->setCheckable(true);
    showDataTb_->setChecked(false);
    //showDataTb_->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    hb->addWidget(showDataTb_);
    hb->addStretch(1);

    //connect(showMetaTb_,SIGNAL(toggled(bool)),
    //	this,SLOT(slotShowMeta(bool)));

    showBg_ = new QButtonGroup(this);
    showBg_->setExclusive(true);
    showBg_->addButton(showMetaTb_, 0);
    showBg_->addButton(showDataTb_, 1);

    connect(showBg_, SIGNAL(buttonClicked(int)),
            this, SLOT(slotShowContents(int)));

    //----------------------
    // Central
    //----------------------

    centralLayout_ = new QStackedLayout;
    layout->addLayout(centralLayout_, 1);

    //----------------------
    // Metadata widget
    //----------------------

    metaWidget_ = new MvQLayerMetaDataWidget();
    centralLayout_->addWidget(metaWidget_);

    //----------------------
    // Data widget
    //----------------------

    dataWidget_ = new MvQLayerDataWidget(scene, plotView);
    centralLayout_->addWidget(dataWidget_);
}


MvQDataWidget::~MvQDataWidget()
{
}

MgQLayerItem* MvQDataWidget::currentLayerFromList()
{
    QListWidgetItem* item = layerList_->currentItem();
    if (!item) {
        return 0;
    }

    int layerIndex = item->data(Qt::UserRole).toInt();
    if (layerIndex >= 0 && layerIndex < sceneItem_->layerItems().count()) {
        return sceneItem_->layerItems().at(layerIndex);
    }
    else {
        return 0;
    }
}

void MvQDataWidget::setCurrentItemForLayerList(QString title)
{
    for (int i = 0; i < layerList_->count(); i++) {
        if (layerList_->item(i)->text() == title) {
            layerList_->setCurrentRow(i, QItemSelectionModel::SelectCurrent);
            return;
        }
    }
}

void MvQDataWidget::setCurrentItemForLayerList(MgQLayerItem* item)
{
    if (!item)
        return;

    int layerIndex = sceneItem_->layerItems().indexOf(item);
    if (layerIndex != -1) {
        for (int i = 0; i < layerList_->count(); i++) {
            if (layerList_->item(i)->data(Qt::UserRole).toInt() == layerIndex) {
                layerList_->setCurrentRow(i, QItemSelectionModel::SelectCurrent);
                break;
            }
        }
    }
}


void MvQDataWidget::slotShowContents(int id)
{
    MgQLayerItem* layer;
    //	int currentId=centralLayout_->currentIndex();

    layer = currentLayerFromList();

    //We need to do it all the time to pick up the current layer stacking order
    //resetLayerList(sceneItem_,layer);

    if (id == 0) {
        if (!metaLoaded_) {
            metaWidget_->reset(sceneItem_, layer);
            metaLoaded_ = true;
        }
        else {
            metaWidget_->setLayer(layer);
        }
    }
    else if (id == 1) {
        if (!dataLoaded_) {
            dataWidget_->reset(sceneItem_, layer);
            dataLoaded_ = true;
        }
        else {
            dataWidget_->setLayer(layer);
        }
    }

    centralLayout_->setCurrentIndex(id);
}

void MvQDataWidget::slotFrameChanged()
{
    switch (centralLayout_->currentIndex()) {
        case 0:
            metaWidget_->slotFrameChanged();
            break;
        case 1:
            dataWidget_->slotFrameChanged();
            break;
        default:
            break;
    }
}

void MvQDataWidget::slotSelectLayerFromList(QListWidgetItem* /*item*/)
{
    int currentId = centralLayout_->currentIndex();
    switch (currentId) {
        case 0:
            metaWidget_->setLayer(currentLayerFromList());
            break;
        case 1:
            dataWidget_->setLayer(currentLayerFromList());
            break;
        default:
            break;
    }
}

void MvQDataWidget::slotPlotScaleChanged()
{
    dataWidget_->updateProbe();
}


void MvQDataWidget::layersAreAboutToChange()
{
    switch (centralLayout_->currentIndex()) {
        case 0:
            if (layerList_->currentItem()) {
                lastSelectedLayerText_ = layerList_->currentItem()->text();
            }
            break;
        case 1:
            if (layerList_->currentItem()) {
                lastSelectedLayerText_ = layerList_->currentItem()->text();
            }
            break;
        default:
            break;
    }
}

void MvQDataWidget::reset(MgQSceneItem* sceneItem)
{
    sceneItem_ = sceneItem;

    MgQLayerItem* layer     = 0;
    MgQLayerItem* lastLayer = 0;

    for (int i = sceneItem_->layerItems().count() - 1; i >= 0; i--) {
        MgQLayerItem* item = sceneItem_->layerItems().at(i);
        lastLayer          = item;

        QString str(item->layer().name().c_str());
        QStringList lst = str.split("/");
        if (!lst.isEmpty()) {
            str = lst.last();
        }

        if (str == lastSelectedLayerText_) {
            layer = item;
        }
    }

    if (!layer)
        layer = lastLayer;


    int currentId = centralLayout_->currentIndex();

    //reset widget load states
    metaLoaded_ = false;
    dataLoaded_ = false;

    resetLayerList(layer);

    switch (currentId) {
        case 0:
            metaWidget_->reset(sceneItem, layer);
            metaLoaded_ = true;
            break;
        case 1:
            dataWidget_->reset(sceneItem, layer);
            dataLoaded_ = true;
        default:
            break;
    }
}

//Update layer selector

void MvQDataWidget::resetLayerList(MgQLayerItem* layer)
{
    resetLayerList(false);
    setCurrentItemForLayerList(layer);
}


void MvQDataWidget::resetLayerList(bool restoreCurrentItem)
{
    if (restoreCurrentItem) {
        if (layerList_->currentItem()) {
            lastSelectedLayerText_ = layerList_->currentItem()->text();
        }
    }

    layerList_->clear();

    if (!sceneItem_)
        return;

    std::map<int, int> stackLevel;
    for (int i = 0; i < sceneItem_->layerItems().count(); i++) {
        stackLevel[sceneItem_->layerItems().at(i)->stackLevel()] = i;
    }

    //Check is needed!!

    for (int i = sceneItem_->layerItems().count() - 1; i >= 0; i--) {
        //  	MgQLayerItem *item=sceneItem->layerItems().at(i);

        MgQLayerItem* item = sceneItem_->layerItems().at(stackLevel[i]);

        QString str(item->layer().name().c_str());
        QStringList lst = str.split("/");
        if (!lst.isEmpty()) {
            str = lst.last();
        }

        QPixmap pix = QPixmap::fromImage(item->preview().scaled(QSize(48, 48), Qt::KeepAspectRatio));
        QPainter painter(&pix);
        painter.setPen(QColor(230, 230, 230));
        painter.drawRect(pix.rect().adjusted(1, 1, -1, -1));

        QListWidgetItem* lstItem = new QListWidgetItem(pix, str);
        lstItem->setData(Qt::UserRole, stackLevel[i]);  // We store the real index
        layerList_->addItem(lstItem);
    }

    if (restoreCurrentItem) {
        setCurrentItemForLayerList(lastSelectedLayerText_);
    }
}

void MvQDataWidget::writeSettings(QSettings& settings)
{
    settings.beginGroup("MvQDataWidget");

    settings.setValue("id", centralLayout_->currentIndex());
    settings.setValue("histoEnabled", metaWidget_->isHistoEnabled());
    settings.setValue("histoVisdefIndex", metaWidget_->histoVisdefCurrentIndex());
    settings.setValue("statsEnabled", metaWidget_->isStatsEnabled());

    settings.endGroup();

    dataWidget_->writeSettings(settings);
}

void MvQDataWidget::readSettings(QSettings& settings)
{
    settings.beginGroup("MvQDataWidget");

    QVariant val;

    val                 = settings.value("id");
    QAbstractButton* tb = showBg_->button((val.isNull()) ? 0 : val.toInt());
    if (tb)
        tb->click();
    else
        showBg_->button(0)->click();

    val = settings.value("histoEnabled");
    metaWidget_->setHistoEnabled((val.isNull()) ? true : val.toBool());

    val = settings.value("histoVisdefIndex");
    metaWidget_->setHistoVisdefInitialIndex((val.isNull()) ? 0 : val.toInt());

    val = settings.value("statsEnabled");
    metaWidget_->setStatsEnabled((val.isNull()) ? true : val.toBool());

    settings.endGroup();

    dataWidget_->readSettings(settings);
}