/***************************** 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 <QDebug>
#include <QMimeData>

#include "MvQKeyModel.h"
#include "MvQPixmapCache.h"

#include "MvQKeyMimeData.h"
#include "MvKeyProfile.h"


MvQKeyModel::MvQKeyModel(MvKeyProfile *profile,DisplayMode mode,QObject *parent) :
         QAbstractItemModel(parent),
         profile_(profile),
         mode_(mode),
         editable_(false),
         pixmaps_(0)
{
}

MvQKeyModel::MvQKeyModel(DisplayMode mode,QObject *parent) :
        QAbstractItemModel(parent),
         profile_(0), 
         mode_(mode), 
         editable_(false),
         pixmaps_(0)
{
}

void MvQKeyModel::profileIsAboutToChange()
{
	beginResetModel();
}

void MvQKeyModel::setKeyProfile(MvKeyProfile  *profile)
{
	profile_=profile;
	
	endResetModel();
}

int MvQKeyModel::columnCount( const QModelIndex& parent) const
{
	switch(mode_)
	{
	case ProfileContentsMode:
   		return 3;
	case AllKeysMode:
		return 2;
	case ShortNameMode:
		return parent.isValid() ? 0 : 1;
	default:
		return 0;
	}
}

int MvQKeyModel::rowCount( const QModelIndex& index) const
{
    	if (!index.isValid() && profile_ !=0 )
	{
		return  profile_->size();
	}
	else
	{
		return 0;
	}
}

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

	if(mode_ == ProfileContentsMode || mode_ == ShortNameMode)
	{
		if(index.column() == 0 || !editable_)
		{	defaultFlags=Qt::ItemIsEnabled |
		   	Qt::ItemIsSelectable;
		}
		else 
		{
			defaultFlags=Qt::ItemIsEnabled |
		  	Qt::ItemIsSelectable |
		   	Qt::ItemIsEditable;
		}


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

	}
	
	else if(mode_ == AllKeysMode)
	{		
		defaultFlags=Qt::ItemIsEnabled |
		   	     Qt::ItemIsSelectable;		
     		
       		return Qt::ItemIsDragEnabled | defaultFlags;
	}
	
	return defaultFlags;
}

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

	if(role == Qt::DisplayRole || role == Qt::ToolTipRole)
	{
 		MvKey  *key=profile_->at(index.row());
  		return label(key,index.row(),index.column(),role);
	}
	else if(role == Qt::DecorationRole && index.column() == 0 && pixmaps_)
	{	
		MvKey  *key=profile_->at(index.row());
		QString name=QString::fromStdString(key->name()); 
		return pixmaps_->pixmap(name).toImage().scaled(QSize(24,24),Qt::KeepAspectRatio,Qt::SmoothTransformation);
	}	
	  
	return  QVariant();
}

bool MvQKeyModel::setData( const QModelIndex & index, const QVariant & value, int role) 
{
	if(!editable_)
		return false;

	if( !index.isValid() || role != Qt::EditRole)
		return false;	

	if(mode_ != ProfileContentsMode)
		return false;

	if(index.column() == 1)
	{	
		MvKey  *key=profile_->at(index.row());
		QString s=value.toString();
		if(s.isEmpty() == false)
		{
			key->setName(s.toStdString());
			emit  dataChanged(index,index);
			return true;
		}
	}
	else if(index.column() == 2)
	{	
		MvKey  *key=profile_->at(index.row());
		QString s=value.toString();
		if(s.isEmpty() == false)
		{
			key->setShortName(s.toStdString());
			emit  dataChanged(index,index);
			return true;
		}
	}	

	return false;

}
QVariant MvQKeyModel::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 );
	
	if(mode_ == ProfileContentsMode)
	{
    		switch ( section ) 
		{
    		case 0: return tr("Index");
    		case 1: return tr("Key name");
    		case 2: return tr("Header name");
    		default: return QVariant();
    		}
	}
	else if(mode_ == AllKeysMode)
	{
    		switch ( section ) 
		{
    		case 0: return tr("Key name");
    		case 1: return tr("Description");
    		default: return QVariant();
    		}
	}

    	return QVariant();
}

QString MvQKeyModel::label(MvKey* key,const int row, const int column,int role ) const
{
	if(mode_ == ProfileContentsMode)
	{
		switch ( column ) 
		{
    		case 0: return QString::number(row+1);
		case 1: return QString::fromStdString(key->name());	
    		case 2: return QString::fromStdString(key->shortName());
		default: return QString();
		}
	}
	else if(mode_ == AllKeysMode)
	{
		switch ( column ) 
		{
		case 0: return QString::fromStdString(key->name());	
    		case 1: 
		{
			QString desc=QString::fromStdString(key->description());
			QString sec=QString::fromStdString(key->metaData("section"));
			QString s=desc;	
			if(!sec.isEmpty())
			{
				QString centre=QString::fromStdString(key->metaData("centre"));
				s+=" (Section: " + sec;
				if(!centre.isEmpty())
				{
					s+=" Centre: " + centre;  
				}
				s+=")";
			}
			return s;
		}
		default: return QString();
		}
	}
	else if(mode_ == ShortNameMode)
	{
		if(column == 0)
		{
		  	if(role == Qt::ToolTipRole)
			{
			  	string cntStr=key->metaData("path_count");
				if(!cntStr.empty())
					return QString();
				else				  
					return QString::fromStdString(key->name());
			}	
			else
			  	return QString::fromStdString(key->shortName());
		}
		else
		{
			return QString();
		}
	}
	
	
	return QString();   	
}

QModelIndex MvQKeyModel::index( int row, int column, const QModelIndex & /*parent*/ ) const
{
   return createIndex(row,column,(void*)0);
}


QModelIndex MvQKeyModel::parent( const QModelIndex & /*index*/ ) const
{
    return QModelIndex();
}


void MvQKeyModel::moveUp(const QModelIndex& index)
{
	if(!index.isValid())
		return;

	beginResetModel();
	moveRow(index.row(),index.row()-1);
	endResetModel();	
}	

void MvQKeyModel::moveDown(const QModelIndex& index)
{
	if(!index.isValid())
		return;

	beginResetModel();
	moveRow(index.row(),index.row()+1);
	endResetModel();
	
}	

void MvQKeyModel::moveRow(int sourceRow,int targetRow)
{
	if(sourceRow < 0 ||  sourceRow >= static_cast<int>(profile_->size()) ||
	   targetRow < 0 ||  targetRow >= static_cast<int>(profile_->size()) ||
           sourceRow == targetRow )
	{
		return;
	}

	profile_->reposition(sourceRow,targetRow);
}


Qt::DropActions MvQKeyModel::supportedDropActions() const
{
	/*if(!editable_)
		return Qt::IgnoreAction;
	else
		return Qt::CopyAction;*/

	return Qt::CopyAction;
}

QStringList MvQKeyModel::mimeTypes() const
 {
	QStringList types;
    	types << "metview/mvkey";
    	return types;
 }

QMimeData* MvQKeyModel::mimeData(const QModelIndexList &indexes) const
 {
     	MvQKeyMimeData *mimeData = new MvQKeyMimeData(this);
     	
	QList<int> procRows;

    	foreach (QModelIndex index, indexes) 
	{
	       	if (index.isValid() && 
		    procRows.indexOf(index.row()) == -1) 
		{
			MvKey *key=profile_->at(index.row());
			mimeData->addKey(key,index.row());
			procRows << index.row();
         	}
     	}

     	return mimeData;
}

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

	if(!profile_)
		return false;

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

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

	const MvQKeyMimeData *keyData=qobject_cast<const MvQKeyMimeData*>(data);

	if(!keyData || keyData->keys().isEmpty())
		return false;

	//Dnd from self --> move rows
	if(keyData->model() == this)
	{
		qDebug() << "self";
		int targetRow=row;
     		if (row != -1)
        		targetRow = row; 
		else if (parent.isValid())
        		targetRow = parent.row();
		else
         		targetRow = rowCount(QModelIndex())-1;
			
		beginResetModel();
	
		QMapIterator<int,MvKey*> it(keyData->keys());
		while(it.hasNext()) 
		{
     			it.next();
			int sourceRow=it.key();
			moveRow(sourceRow,targetRow);	
			break;
		}

		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;
}

