/***************************** 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 "MvQProductBrowser.h"

#include <QApplication>
#include <QCloseEvent>
#include <QDialogButtonBox>
#include <QDebug>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QMouseEvent>
#include <QPainter>
#include <QPushButton>
#include <QSettings>
#include <QVBoxLayout>

#include "MvQIconMimeData.h"
#include "MvQIconProvider.h"

#include "IconClass.h"
#include "Path.h"
#include "Product.h"

QMap<Product*, QPixmap> MvQProductModel::pixmaps_;
int MvQProductModel::itemHeight_;

//=====================================================
//
// MvQProductListDelegate
//
//=====================================================

MvQProductListDelegate::MvQProductListDelegate(MvQProductModel* prodModel, int itemHeight, QWidget* parent) :
    QStyledItemDelegate(parent),
    prodModel_(prodModel),
    itemHeight_(itemHeight)
{
}

void MvQProductListDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,
                                   const QModelIndex& index) const
{
    if (index.column() == 0) {
        QStyleOptionViewItemV4 vopt(option);
        initStyleOption(&vopt, index);

        const QStyle* style   = vopt.widget ? vopt.widget->style() : QApplication::style();
        const QWidget* widget = vopt.widget;

        //int height=option.rect.height();

        //Get font size
        QFont font = QApplication::font();
        QFontMetrics fm(font);
        int fontSize = fm.height() + 4;

        //Save painter state
        painter->save();

        //Highlight
        if (option.state & QStyle::State_HasFocus)
            painter->fillRect(option.rect, option.palette.highlight());

        //Draw icon
        QPixmap pixmap = index.data(Qt::DecorationRole).value<QPixmap>();
        QRect iconRect = style->subElementRect(QStyle::SE_ItemViewItemDecoration, &vopt, widget);
        painter->drawPixmap(iconRect, pixmap);

        //Draw icon border
        painter->setPen(QColor(230, 230, 230));
        painter->drawRect(iconRect);

        //-------------------
        // Pushbuttons
        //-------------------

        int buttonWidth  = 0;
        int buttonHeight = fontSize + 4;
        int buttonY      = option.rect.bottomRight().y() - 3 - buttonHeight;

        //Vis pb
        QStyleOptionButton visPbOpt;
        visPbOpt.text  = "Visualise";
        visPbOpt.state = QStyle::State_Active | QStyle::State_Enabled;

        buttonWidth   = fm.width(visPbOpt.text) + 6;
        visPbOpt.rect = QRect(option.rect.width() - 6 - buttonWidth,
                              buttonY,
                              buttonWidth,
                              buttonHeight);

        style->drawControl(QStyle::CE_PushButton, &visPbOpt, painter, widget);
        prodModel_->setData(index, visPbOpt.rect, MvQProductModel::FolderPbRole);

        //Open pb
        QStyleOptionButton folderPbOpt;
        folderPbOpt.text  = "Open";
        folderPbOpt.state = QStyle::State_Active | QStyle::State_Enabled;

        buttonWidth      = fm.width(folderPbOpt.text) + 6 + 16 + 2;
        folderPbOpt.rect = QRect(visPbOpt.rect.topLeft().x() - 16 - buttonWidth,
                                 buttonY,
                                 buttonWidth,
                                 buttonHeight);

        folderPbOpt.icon     = MvQIconProvider::pixmap(IconClass::find("FOLDER"), 16);
        folderPbOpt.iconSize = QSize(16, 16);

        style->drawControl(QStyle::CE_PushButton, &folderPbOpt, painter, widget);
        prodModel_->setData(index, folderPbOpt.rect, MvQProductModel::FolderPbRole);

        //Draw separator line
        painter->setPen(QColor(230, 230, 230));
        painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight());

        //-----------------------
        // Title + Description
        //-----------------------

        font.setBold(true);
        painter->setFont(font);
        if (option.state & QStyle::State_HasFocus)
            painter->setPen(option.palette.highlightedText().color());
        else
            painter->setPen(option.palette.text().color());

        //Title
        int textWidth = option.rect.width() - (iconRect.x() + iconRect.width() + 5) - 10;

        QString title = index.data(Qt::DisplayRole).toString();
        QRect titleRect(iconRect.topRight().x() + 10, option.rect.y() + 3,
                        textWidth, fontSize + 7);

        painter->drawText(titleRect, Qt::AlignLeft, title);

        textWidth = folderPbOpt.rect.x() - 15 - (iconRect.topRight().x() + 10);

        //Description
        /*font.setBold(false);
		painter->setFont(font);
		
		QString desc=index.data(MvQProductModel::DescriptionRole).toString();
		QRect descRect(titleRect.x(),
			       titleRect.bottomLeft().y()+7,
			       textWidth,
			       fontSize*2+10);
			       	
				
		painter->drawText(descRect,Qt::TextWordWrap | Qt::AlignLeft,desc);*/


        //restore painter state
        painter->restore();
    }
    else {
        QStyledItemDelegate::paint(painter, option, index);
    }
}
QSize MvQProductListDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    QSize size = QStyledItemDelegate::sizeHint(option, index);

    if (index.column() == 0) {
        size.setHeight(itemHeight_);
    }
    else {
        size += QSize(0, 6);
    }

    return size;
}

//=====================================================
//
// MvQProductListView
//
//=====================================================

MvQProductListView::MvQProductListView(QWidget* parent) :
    QListView(parent)
{
}

void MvQProductListView::mousePressEvent(QMouseEvent* event)
{
    QModelIndex index = indexAt(event->pos());
    if (index.isValid()) {
        if (model()->data(index, MvQProductModel::FolderPbRole).toRect().contains(event->pos())) {
            emit openFolder(index);
        }
    }

    QAbstractItemView::mousePressEvent(event);
}

//=============================================
//
// MvQProductModel
//
//=============================================

MvQProductModel::MvQProductModel(int itemHeight, QObject* parent) :
    QAbstractItemModel(parent)
{
    itemHeight_ = itemHeight;
}

MvQProductModel::~MvQProductModel()
{
}

void MvQProductModel::setProduct(const vector<Product*>& data)
{
    beginResetModel();
    folderPbRect_.clear();
    visPbRect_.clear();
    data_ = data;
    endResetModel();
}

int MvQProductModel::columnCount(const QModelIndex& parent) const
{
    return parent.isValid() ? 0 : 1;
}

int MvQProductModel::rowCount(const QModelIndex& index) const
{
    if (!index.isValid()) {
        return static_cast<int>(data_.size());
    }
    else {
        return 0;
    }
}

QVariant MvQProductModel::data(const QModelIndex& index, int role) const
{
    if (!index.isValid() || index.column() != 0) {
        return QVariant();
    }

    if (index.row() < 0 || index.row() >= static_cast<int>(data_.size())) {
        return QVariant();
    }

    int row = index.row();

    switch (role) {
        case Qt::DecorationRole:
            return MvQProductModel::pixmap(data_.at(row));

        case Qt::DisplayRole:
            return QString::fromStdString(data_.at(row)->title());

        case DescriptionRole:
        case Qt::ToolTipRole:
            return QString::fromStdString(data_.at(row)->description());

        case FolderPbRole:
            return folderPbRect_.value(index);

        case VisPbRole:
            return folderPbRect_.value(index);

        case PathRole:
            return QString::fromStdString(data_.at(row)->path());

        default:
            break;
    }

    return QVariant();
}


bool MvQProductModel::setData(const QModelIndex& index, QRect rect, int role)
{
    if (!index.isValid()) {
        return false;
    }

    if (role == FolderPbRole) {
        folderPbRect_[index] = rect;
        return true;
    }
    else if (role == VisPbRole) {
        visPbRect_[index] = rect;
        return true;
    }

    return false;
}

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


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


QPixmap MvQProductModel::pixmap(Product* item)
{
    if (!item || !item->hasImage())
        return QPixmap();

    QMap<Product*, QPixmap>::iterator it = pixmaps_.find(item);
    if (it != pixmaps_.end())
        return it.value();

    QImage img(QString::fromStdString(item->imagePath()));

    QPixmap pix = QPixmap::fromImage(img.scaledToHeight(itemHeight_ - 8, Qt::SmoothTransformation));

    pixmaps_[item] = pix;

    return pix;
}

//=============================================
//
// MvQProductListWidget
//
//=============================================

MvQProductListWidget::MvQProductListWidget(QWidget* parent) :
    QListWidget(parent)
{
    setAcceptDrops(false);
    setDragEnabled(true);
}

void MvQProductListWidget::mousePressEvent(QMouseEvent* event)
{
    if (event->button() == Qt::LeftButton) {
        startPos_ = event->pos();
    }

    QListView::mousePressEvent(event);
}

void MvQProductListWidget::mouseMoveEvent(QMouseEvent* event)
{
    if (event->buttons() & Qt::LeftButton) {
        int distance = (event->pos() - startPos_).manhattanLength();
        if (distance >= QApplication::startDragDistance()) {
            performDrag();
        }
    }

    QListView::mouseMoveEvent(event);
}

void MvQProductListWidget::performDrag()
{
    /*QListWidgetItem *item=currentItem();
	
	if(!item)
		return;
		
	const IconClass& iconClass=IconClass::find(item->data(Qt::UserRole).toString().toStdString());
	
	
	MvQNewIconMimeData::IconDefType type=(iconDefType_ == UserDef)?
	                                     (MvQNewIconMimeData::UserDef):
	                                     (MvQNewIconMimeData::SystemDef);
	
	MvQNewIconMimeData *mimeData= new MvQNewIconMimeData(iconClass.name().c_str(),type);
	
	QDrag *drag = new QDrag(this);
	drag->setPixmap(MvQPixmapProvider::current()->pixmap(iconClass));
	drag->setMimeData(mimeData);	
		
	if(drag->exec(Qt::CopyAction)  == Qt::CopyAction)
	{
	}*/
}

//=====================================================
//
// MvQProductBrowser
//
//=====================================================

MvQProductBrowser::MvQProductBrowser(QWidget* parent) :
    QDialog(parent)
{
    //setAttribute(Qt::WA_DeleteOnClose);

    setWindowTitle("Metview - products");

    //Initial size
    resize(QSize(600, 800));

    //layout
    QVBoxLayout* vb = new QVBoxLayout;
    vb->setSpacing(0);
    vb->setContentsMargins(1, 1, 1, 1);
    setLayout(vb);

    //Search
    QLabel* label = new QLabel("Search:");
    searchLine_   = new QLineEdit(this);

    QHBoxLayout* hb = new QHBoxLayout(this);
    hb->addWidget(label);
    hb->addWidget(searchLine_, 1);
    vb->addLayout(hb);

    searchList_ = new MvQProductListView(this);
    vb->addWidget(searchList_);

    //Item height in view
    QFont font = QApplication::font();
    QFontMetrics fm(font);
    int itemHeight = fm.height() * 5 + 10;
    if (itemHeight < 58)
        itemHeight = 58;

    model_ = new MvQProductModel(itemHeight, this);
    searchList_->setModel(model_);

    MvQProductListDelegate* delegate = new MvQProductListDelegate(model_, itemHeight, this);
    searchList_->setItemDelegate(delegate);

    connect(searchLine_, SIGNAL(textChanged(QString)),
            this, SLOT(slotSearch(QString)));

    connect(searchList_, SIGNAL(openFolder(const QModelIndex&)),
            this, SLOT(slotOpenFolder(const QModelIndex&)));

    // Buttons
    buttonBox_ = new QDialogButtonBox(this);

    buttonBox_->addButton(QDialogButtonBox::Close);

    connect(buttonBox_, SIGNAL(clicked(QAbstractButton*)),
            this, SLOT(slotButtonClicked(QAbstractButton*)));

    vb->addWidget(buttonBox_);
}

MvQProductBrowser::~MvQProductBrowser()
{
}

void MvQProductBrowser::closeEvent(QCloseEvent* event)
{
    //emit aboutToClose(this);
    close();
    event->accept();
}

void MvQProductBrowser::slotButtonClicked(QAbstractButton* button)
{
    if (!button)
        return;

    if (buttonBox_->standardButton(button) == QDialogButtonBox::Close) {
        close();
        accept();
    }
}
void MvQProductBrowser::slotItemSelected(QListWidgetItem* /*item*/)
{
    /*QMap<const IconClass&,QListWidgetItem*>::iterator it=classes_.find(item);
	if(it != classes_.end())
		selected_=it.value();  */

    //accept();
}

void MvQProductBrowser::slotSearch(QString str)
{
    vector<Product*> res;

    if (str.simplified().isEmpty()) {
        model_->setProduct(res);
        return;
    }

    Product::find(str.toStdString(), res);
    model_->setProduct(res);

    /*searchList_->clear();
	
	
	
	for(vector<Product*>::iterator it=res.begin(); it != res.end(); it++)
	{			
		if((*it)->hasImage())
		{
		  	QImage img(QString::fromStdString((*it)->imagePath()));
					  
	  		QListWidgetItem *item=new QListWidgetItem(QPixmap::fromImage(img.scaled(60,45,Qt::KeepAspectRatio,Qt::SmoothTransformation)),
				              QString::fromStdString((*it)->title()));
						
			item->setData(Qt::UserRole,QString::fromStdString((*it)->title()));
			searchList_->addItem(item);
		}	
	}*/
}

void MvQProductBrowser::slotOpenFolder(const QModelIndex& index)
{
    emit openFolderInWin(model_->data(index, MvQProductModel::PathRole).toString());
}

void MvQProductBrowser::writeSettings()
{
}

void MvQProductBrowser::readSettings()
{
}
