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

#include <QAction>
#include <QDebug>
#include <QLabel>
#include <QMenu>
#include <QMouseEvent>
#include <QPainter>
#include <QToolButton>

#include "MvQPalette.h"
#include "MvQRequestPanelHelp.h"

#include "LineFactory.h"
#include "RequestPanel.h"

//==============================================
//
// MvQColourListWidget
//
//==============================================

MvQColourListWidget::MvQColourListWidget(QWidget *parent) : 
  QWidget(parent),
  edited_(false),
  cellWidth_(0),
  currentCell_(-1),
  editorGapX_(2),
  editorGapY_(4)
{
  	blackPen_=QPen(Qt::black,2.,Qt::SolidLine);
  	whitePen_=QPen(Qt::white,2.,Qt::SolidLine);
  
	setContextMenuPolicy(Qt::ActionsContextMenu);	
	
	insertBeforeAc_=new QAction(this);
	insertBeforeAc_->setText(tr("Insert before cell"));
	insertBeforeAc_->setData("insertBefore");
	insertBeforeAc_->setIcon(QPixmap(":/desktop/insertBefore.svg"));
	insertBeforeAc_->setToolTip(tr("Insert before cell"));
	
	addAction(insertBeforeAc_);
	
	connect(insertBeforeAc_,SIGNAL(triggered()),
                this, SLOT(slotInsertBeforeCell()));

	insertAfterAc_=new QAction(this);
	insertAfterAc_->setText(tr("Insert after cell"));
	insertAfterAc_->setData("insertAfter");
	insertAfterAc_->setIcon(QPixmap(":/desktop/insertAfter.svg"));
	insertAfterAc_->setToolTip(tr("Insert after cell"));
	
	addAction(insertAfterAc_);
	
	connect(insertAfterAc_,SIGNAL(triggered()),
                this, SLOT(slotInsertAfterCell()));
		
	deleteCellAc_=new QAction(this);
	deleteCellAc_->setText(tr("Delete cell"));
	deleteCellAc_->setData("deleteCell");
	deleteCellAc_->setIcon(QPixmap(":/desktop/deleteCell.svg"));
	deleteCellAc_->setToolTip(tr("Remove cell"));	
	
	addAction(deleteCellAc_);
	
	connect(deleteCellAc_,SIGNAL(triggered()),
                this, SLOT(slotDeleteCell()));	
}  


void MvQColourListWidget::checkActionState()
{
  	if(colours_.count() <=1)
	  	deleteCellAc_->setEnabled(false);
	else
	  	deleteCellAc_->setEnabled(true);
}

void MvQColourListWidget::setColours(QList<QColor> cols)
{
  	colours_=cols;
	
	if(currentCell_==-1 || currentCell_>= colours_.count())
	{	
		setCurrentCell(0);
	}	
	else
	{  
		createPixmap();
		update();
	}
	
	checkActionState();
}	

void MvQColourListWidget::resizeEvent(QResizeEvent */*event*/) 
{
	createPixmap();
	update();
}

void MvQColourListWidget::changeEvent(QEvent *event)
{
    if(event->type() == QEvent::EnabledChange)
    {
        createPixmap();
        update();
    }
    else
    {
        QWidget::changeEvent(event);
    }
}

void MvQColourListWidget::paintEvent(QPaintEvent */*event*/)
{
	QPainter painter(this);

    if(!pix_.isNull())
		painter.drawPixmap(0,0,pix_);
	
    renderCurrentCell(&painter);
}

void MvQColourListWidget::mousePressEvent(QMouseEvent *event)
{	 	
	setCurrentCell(event->pos());
	//if(colours_.count() == 1)
	//{	
	emit singleCellClicked();
	//}	
}

void MvQColourListWidget::setCurrentCell(QPoint pos)
{
  	int i=pos.x()/cellWidth_;
	setCurrentCell(i);
}

void MvQColourListWidget::setCurrentCell(int index)
{
  	if(index >=0 && index < colours_.count())
	{
	  	currentCell_=index;
		update();
		emit currentChanged(colours_[currentCell_]);
	}
}

void MvQColourListWidget::createPixmap()
{
    if(!isEnabled())
    {
        pix_=QPixmap(width(),height());
        pix_.fill(palette().color(QPalette::Disabled,QPalette::Button));
        return;
    }

    QFont font;
    QFontMetrics fm(font);
    int h=height(); //fm.height()+4;
   	int w=width()/((colours_.count()>0)?colours_.count():1);
	
	cellWidth_=w;
	
	pix_=QPixmap(width(),h);
	QPainter painter(&pix_);
    painter.setPen(QColor(40,40,40));
	
	if(edited_)
	{
	  	pix_.fill(Qt::gray);
		
		for(int i=0; i < colours_.count(); i++)
		{
			painter.setBrush(colours_[i]);
	  		int cx=i*cellWidth_;
			int cy=editorGapY_;
			int cw=cellWidth_;
            int ch=h-2*editorGapY_-1;
			
			if(i==0)
			{	
				cx+=editorGapX_;
				cw-=editorGapX_;
			}
			else if(i==colours_.count()-1)
			{				  	
				cw-=editorGapX_;
			}	

            QRect r(cx,cy,cw,ch);

            if(colours_[i].alpha() != 255)
                MvQPalette::paintAlphaBg(&painter,r);

            painter.drawRect(r);
		}
	}
	else
	{
	  	for(int i=0; i < colours_.count(); i++)
		{
			painter.setBrush(colours_[i]);
	  		int cx=i*cellWidth_;
			int cy=0;
			int cw=cellWidth_;
            int ch=h-1;

            QRect r(cx,cy,cw,ch);

            if(colours_[i].alpha() != 255)
                MvQPalette::paintAlphaBg(&painter,r);

            painter.drawRect(r);
		}
	}	
	
	if(colours_.count() == 0)
	  	pix_.fill(palette().color(QPalette::Window));
}	

void MvQColourListWidget::renderCurrentCell(QPainter* painter)
{	
	if(edited_ and colours_.count()> 1 and currentCell_ >= 0 && currentCell_ < colours_.count())
	{	  		  		
		int cx=currentCell_*cellWidth_;
		int cy=0;
		int cw=cellWidth_;
        int ch=pix_.height()-1;
			
		if(currentCell_==0)
		{	
			cx+=editorGapX_;
			cw-=editorGapX_;
		}
		else if(currentCell_==colours_.count()-1)
		{				  	
			cw-=editorGapX_;
		}	
		
        QRect r(cx,cy,cw,ch);

        if(colours_[currentCell_].alpha() != 255)
            MvQPalette::paintAlphaBg(painter,r);

        painter->setPen(blackPen_);
        painter->fillRect(r,colours_[currentCell_]);
		painter->drawRect(cx-1,cy+1,cw+2,ch-2);		
	}	
}

QColor MvQColourListWidget::currentColour() const
{
  	if(currentCell_ >= 0 && currentCell_ < colours_.count())
	  	return colours_[currentCell_];
	
	return QColor();
}

void MvQColourListWidget::setCurrentColour(QColor col)
{
	if(col.isValid() &&  
	   currentCell_ >= 0 && currentCell_ < colours_.count()) 
	{
		colours_[currentCell_]=col;
		createPixmap();
		update();
		emit changed();
	}	  
}

void MvQColourListWidget::slotInsertBeforeCell()
{
  	insertBeforeCell(currentCell_);
}

void MvQColourListWidget::slotInsertAfterCell()
{
  	insertAfterCell(currentCell_);
}

void MvQColourListWidget::slotDeleteCell()
{
  	deleteCell(currentCell_);
}

void MvQColourListWidget::deleteCell(int index)
{
	if(colours_.count() > 1 && index >=0 && index < colours_.count() )
	{
	  	colours_.removeAt(index);
		
		createPixmap();
		if(index < colours_.count()-1)
			setCurrentCell(index);
		else
		  	setCurrentCell(colours_.count()-1);
		
		emit changed();
		
		checkActionState();
	}
}


void MvQColourListWidget::insertBeforeCell(int index)
{
	if(index >=0 && index < colours_.count())
	{
	  	QColor col=colours_[index];
	  	colours_.insert(index,col);
				
		createPixmap();
		setCurrentCell(index);
		emit changed();
	}
}


void MvQColourListWidget::insertAfterCell(int index)
{
	if(index >=0 && index < colours_.count())
	{
	  	QColor col=colours_[index];
	  	colours_.insert(index+1,col);
				
		createPixmap();
		setCurrentCell(index+1);
		emit changed();
	}
}

void MvQColourListWidget::setEdited(bool edited)
{
	if(edited_ != edited)
	{
	  	edited_=edited;
		createPixmap();
		update();
	}
}	


//==============================================
//
// MvQColourListLine
//
//==============================================

MvQColourListLine::MvQColourListLine(RequestPanel& owner,const Parameter& param) :
		   MvQRequestPanelLine(owner,param) 
{
	widget_ = new MvQColourListWidget(parentWidget_);
	
	QFont font;
    QFontMetrics fm(font);
    //int h=fm.height()+4;
	
	owner_.addWidget(widget_,row_,WidgetColumn);
	
	connect(widget_,SIGNAL(currentChanged(QColor)),
		this,SLOT(slotCurrentChanged(QColor)));
		
	connect(widget_,SIGNAL(changed()),
		this,SLOT(slotListChanged()));
		
	connect(widget_,SIGNAL(singleCellClicked()),	
		this,SLOT(slotSingleCellClicked()));	
}


void MvQColourListLine::buildHelper()
{	
	MvQRequestPanelLine::buildHelper();

	//Customisation
	if(helper_)
	  	helper_->setExternalActions(widget_->actions()); 
	
	/*connect(helper_,SIGNAL(insertBefore()),
                widget_,SLOT(slotInsertBeforeCell()));
		
	connect(helper_,SIGNAL(insertAfter()),
                widget_,SLOT(slotInsertAfterCell()));
			
	connect(helper_,SIGNAL(deleteCell()),
                widget_,SLOT(slotDeleteCell()));*/	
		
}	
	
void MvQColourListLine::slotHelperOpened(bool b)
{
 	widget_->setEdited(b); 
	updateHelper();
}  

void MvQColourListLine::refresh(const vector<string>& values)
{
	if(values.size() > 0)
	{
		QList<QColor> colours;
		
		for(int i=0; i < static_cast<int>(values.size()); i++)
		{
		 	QString name=QString::fromStdString(values[i]);			
			colours << MvQPalette::magics(values[i]);
		}
		
		widget_->setColours(colours);
	}
	
	//changed_ = false;
}


void MvQColourListLine::slotListChanged()
{
	vector<string> vals;
	foreach(QColor col,widget_->colours())
	{
		vals.push_back(MvQPalette::toString(col));	  		  
	}  
	
	owner_.set(param_.name(),vals);
}  

void MvQColourListLine::slotSingleCellClicked()
{
  	if(helpTb_)	
	{			
		if(!helpTb_->isChecked())
		 	helpTb_->toggle();
	}
}  

void MvQColourListLine::updateHelper()
{
  	if(!helper_)
		return;

	vector<string> vals;	
	vals.push_back(MvQPalette::toString(widget_->currentColour()));
	helper_->refresh(vals);
}  		

void MvQColourListLine::slotCurrentChanged(QColor)
{
	updateHelper();	
}

void MvQColourListLine::slotHelperEdited(const vector<string>& vals)
{
	if(vals.size() == 0)
	  	return;

	QString name=QString::fromStdString(vals[0]);
	widget_->setCurrentColour(MvQPalette::magics(vals[0]));
}

static LineMaker<MvQColourListLine> maker1("colourlist");
