/***************************** 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 <QApplication>
#include <QBrush>
#include <QColor>
#include <QDebug>
#include <QHBoxLayout>
#include <QLabel>
#include <QMimeData>
#include <QPainter>
#include <QSlider>
#include <QStringList>
#include <QStyle>

#include "MvQPlaceMark.h"
#include "MvQPlaceMarkMimeData.h"
#include "MvQPlaceMarkModel.h"

MvQPlaceMarkModel::MvQPlaceMarkModel()
{
    root_ = 0;
}

void MvQPlaceMarkModel::dataIsAboutToChange()
{
    beginResetModel();
}


void MvQPlaceMarkModel::setRootNode(MvQPlaceMarkNode* root)
{
    root_ = root;

    //Reset the model (views will be notified)
    endResetModel();
}


int MvQPlaceMarkModel::columnCount(const QModelIndex& /* parent */) const
{
    return 4;
}

int MvQPlaceMarkModel::rowCount(const QModelIndex& parent) const
{
    if (!root_)
        return 0;

    if (parent.column() > 0) {
        return 0;
    }

    MvQPlaceMarkNode* parentNode = nodeFromIndex(parent);
    if (!parentNode)
        return 0;

    return parentNode->children().count();
}

Qt::ItemFlags MvQPlaceMarkModel::flags(const QModelIndex& index) const
{
    Qt::ItemFlags defaultFlags;

    if (index.column() == 0)
        defaultFlags = Qt::ItemIsEnabled |
                       Qt::ItemIsSelectable |
                       Qt::ItemIsEditable |
                       Qt::ItemIsUserCheckable;
    else
        defaultFlags = Qt::ItemIsEnabled |
                       Qt::ItemIsSelectable;
    //Qt::ItemIsEditable;

    if (index.isValid())
        return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
    else
        return Qt::ItemIsDropEnabled | defaultFlags;
}

QVariant MvQPlaceMarkModel::data(const QModelIndex& index, int role) const
{
    if (!index.isValid()) {
        return QVariant();
    }

    MvQPlaceMarkNode* node = nodeFromIndex(index);
    if (!node)
        return QVariant();

    if (role == Qt::CheckStateRole) {
        if (index.column() != 0)
            return QVariant();

        if (node->isVisible() == true)
            return QVariant(Qt::Checked);
        else
            return QVariant(Qt::Unchecked);
    }
    else if (role == Qt::DisplayRole) {
        return label(node, index.row(), index.column());
    }
    else if (role == Qt::DecorationRole && index.column() == 0) {
        return QIcon(node->pixmap());
    }
    else if (role == Qt::ForegroundRole && node->isOutOfPlot()) {
        return QBrush(QColor(100, 100, 100));
    }

    return QVariant();
}

bool MvQPlaceMarkModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
    if (!index.isValid()) {
        return false;
    }
    if (role == Qt::CheckStateRole && index.column() == 0) {
        MvQPlaceMarkNode* node = nodeFromIndex(index);

        if (!node)
            return false;

        bool checked = (value.toInt() == Qt::Checked) ? true : false;
        if (checked != node->isVisible()) {
            beginResetModel();
            node->setVisible(checked);
            endResetModel();

            //emit dataChanged(index,index);

            emit visibilityChanged();

            //The tree will manage this
            //node->setVisible(checked);

            qDebug() << "setData";
            //emit  dataChanged(index,index);

            return true;
        }
    }

    /*else if(role == Qt::DisplayRole && index.column() == 1)
	{
		MgQPlaceMarkNode* layer=rowToPlaceMark(index.row()); 
		
		float alpha = 1.-value.toDouble()/100.;

		layer->setPlaceMarkAlpha(alpha);

		emit  dataChanged(index,index);

		emit  layerUpdate();

		return true;
	}*/

    return false;
}
QVariant MvQPlaceMarkModel::headerData(const int section, const Qt::Orientation orient, const int role) const
{
    if (orient != Qt::Horizontal || role != Qt::DisplayRole)
        return QAbstractItemModel::headerData(section, orient, role);

    switch (section) {
        case 0:
            return tr("Name");
        case 1:
            return tr("X Pos");
        case 2:
            return tr("Y Pos");
        case 3:
            return tr("Data");
    }

    return QVariant();
}

QString MvQPlaceMarkModel::label(MvQPlaceMarkNode* node, const int /*row*/, const int column) const
{
    switch (column) {
        case 0: {
            return node->name();
        }
        case 1: {
            return QString::number(node->coordinates().x());
        }
        case 2: {
            return QString::number(node->coordinates().y());
        }
        case 3: {
            if (!node->layerData().isEmpty()) {
                QString s;
                foreach (QString t, node->layerData().at(0)) {
                    if (!t.isEmpty()) {
                        s += " ";
                        s += t;
                    }
                }
                return s;
            }
            else {
                return QString();
            }
        }

        default:
            return QString();
    }
}

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

    MvQPlaceMarkNode* parentNode = nodeFromIndex(parent);
    MvQPlaceMarkNode* childNode  = parentNode->children().at(row);

    if (!childNode)
        return QModelIndex();

    return createIndex(row, column, childNode);
}

MvQPlaceMarkNode* MvQPlaceMarkModel::nodeFromIndex(const QModelIndex& index) const
{
    if (index.isValid()) {
        return static_cast<MvQPlaceMarkNode*>(index.internalPointer());
    }
    else {
        return root_;
    }
}

QModelIndex MvQPlaceMarkModel::parent(const QModelIndex& child) const
{
    MvQPlaceMarkNode* node = nodeFromIndex(child);
    if (!node)
        return QModelIndex();

    MvQPlaceMarkNode* parentNode = node->parent();
    if (!parentNode)
        return QModelIndex();

    MvQPlaceMarkNode* grandParentNode = parentNode->parent();
    if (!grandParentNode)
        return QModelIndex();

    int row = grandParentNode->children().indexOf(parentNode);
    return createIndex(row, 0, parentNode);
}

QModelIndex MvQPlaceMarkModel::indexFromNode(MvQPlaceMarkNode* node) const
{
    if (node != 0 && node->parent() != 0) {
        int row = node->parent()->children().indexOf(node);
        if (row != -1) {
            return createIndex(row, 0, node);
        }
    }

    return QModelIndex();
}

void MvQPlaceMarkModel::updateItem(const QModelIndex& ind)
{
    QModelIndex index1 = index(ind.row(), 0, ind.parent());
    QModelIndex index2 = index(ind.row(), columnCount() - 1, ind.parent());
    emit dataChanged(index1, index2);
}


void MvQPlaceMarkModel::slotItemUpdated()
{
    MvQPlaceMarkItem* item = static_cast<MvQPlaceMarkItem*>(sender());
    if (!item || !item->placeMark())
        return;

    QModelIndex index0 = indexFromNode(item->placeMark());
    QModelIndex index1 = index(index0.row(), 0, index0.parent());
    QModelIndex index2 = index(index0.row(), columnCount() - 1, index0.parent());
    emit dataChanged(index1, index2);
}


Qt::DropActions MvQPlaceMarkModel::supportedDropActions() const
{
    return Qt::CopyAction;
}

QStringList MvQPlaceMarkModel::mimeTypes() const
{
    QStringList types;
    types << "metview/mvplacemark";
    return types;
}

QMimeData* MvQPlaceMarkModel::mimeData(const QModelIndexList& indexes) const
{
    qDebug() << "source:" << indexes;

    MvQPlaceMarkMimeData* mimeData = new MvQPlaceMarkMimeData(this);

    QList<int> procRows;

    foreach (QModelIndex index, indexes) {
        if (index.isValid() &&
            procRows.indexOf(index.row()) == -1) {
            MvQPlaceMarkNode* node = nodeFromIndex(index);
            mimeData->addPlaceMark(node);
            procRows << index.row();
        }
    }

    return mimeData;
}

bool MvQPlaceMarkModel::dropMimeData(const QMimeData* data,
                                     Qt::DropAction action, int row, int column, const QModelIndex& parent)
{
    //if(!profile_)
    //	return false;

    qDebug() << "target:" << row << column << parent;

    if (action == Qt::IgnoreAction)
        return true;

    if (!data->hasFormat("metview/mvplacemark"))
        return false;

    const MvQPlaceMarkMimeData* nodeData = qobject_cast<const MvQPlaceMarkMimeData*>(data);

    if (!nodeData)
        return false;

    //Dnd from self --> move rows
    if (nodeData->model() == this) {
        qDebug() << "self";


        /*foreach(MvQPlaceMarkNode* n,nodeData->placeMark()) 
		{     			
			QModelIndex i=indexFromNode(n);
			removeRows(i.row(),1,i.parent());
			n->removeChild(n);
		}*/


        MvQPlaceMarkNode* parentNode = nodeFromIndex(parent);
        int targetRow                = row;

        //Parent hast to be a folder
        if (parentNode->type() != MvQPlaceMarkNode::FolderType) {
            parentNode = parentNode->parent();
            if (!parentNode || parentNode->type() == MvQPlaceMarkNode::FolderType) {
                //Root is alwas a folder
                parentNode = root_;
            }
        }

        QModelIndex targetParent = indexFromNode(parentNode);
        targetRow                = rowCount(targetParent);

        qDebug() << targetRow << targetParent;

        beginResetModel();


        foreach (MvQPlaceMarkNode* n, nodeData->placeMark()) {
            if (n->parent())
                n->parent()->removeChild(n);
            parentNode->addChild(n);
        }

        endResetModel();
    }

    //Dnd from another model --> insert new row
    /*else	
	{
		qDebug() << "other";
		beginResetModel();
		QMapIterator<int,MvKey*> it(keyData->keys());
		while(it.hasNext()) 
		{
     			it.next();
			MvKey *key=it.value()->clone();	
			profile_->addKey(key);
		}
		endResetModel();		
	}*/

    return true;
}
