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

#include <QApplication>
#include <QCheckBox>
#include <QColorDialog>
#include <QComboBox>
#include <QDebug>
#include <QDoubleValidator>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QIntValidator>
#include <QLabel>
#include <QLayout>
#include <QLineEdit>
#include <QListWidget>
#include <QRadioButton>
#include <QSlider>
#include <QTextEdit>
#include <QToolButton>
#include <QVBoxLayout>


#include "MvRequest.h"

MvQGuiItem::MvQGuiItem(MvRequest* r,QGridLayout *parentLayout) : row_(0)
{
	//Toggle to indicate default/non-default settings
	defaultTb_ = new QToolButton;
	defaultTb_->setObjectName(QString::fromUtf8("guiItemDefaultTb"));
	defaultTb_->setCheckable(true);
	defaultTb_->setChecked(true);
	defaultTb_->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum));
	defaultTb_->setMaximumSize(QSize(10,10));

	//name label
	const char *name;	
	r->getValue(name,"name",0);
	name_=QString(name);	
	nameLabel_=new QLabel(name_);

	row_=parentLayout->rowCount();
	parentLayout->addWidget(defaultTb_,row_,MvQGuiItem::DefaultColumn);
	parentLayout->addWidget(nameLabel_,row_,MvQGuiItem::NameColumn);
}

MvQGuiItem::~MvQGuiItem()
{
	delete defaultTb_;
	delete nameLabel_;
}

MvQComboBoxGuiItem::MvQComboBoxGuiItem(MvRequest* r, QGridLayout *parentLayout) : MvQGuiItem(r,parentLayout)
{
	//Combo
	combo_ = new QComboBox;
	//nameLabel_->setBuddy(combo_);
	
	//Add to layout
	parentLayout->addWidget(combo_,row_,MvQGuiItem::WidgetColumn);

	//Populate combo

	//Check if a source specified
	const char *source;	
	r->getValue(source,"source",0);
	if(source)
	{
		source_=QString(source);
		if(source_ == "*")
			source_.clear();
	}
	
	//If there is no source use "values" to populate the combo
	if(source_.isEmpty() == true) 
	{
		QStringList str;
		int cnt = r->iterInit("values");
		for(int i=0; i<cnt; ++i)
		{
			const char *cpt;
			r->iterGetNextValue(cpt);
			str << QString(cpt);
		}				
		combo_->addItems(str);	

		//Set to default value
		const char* dval;
		r->getValue(dval,"default",0);
		int dindex=str.indexOf(QString(dval));
		if(dindex != -1)
		{
			combo_->setCurrentIndex(dindex);
		}
	}
}

MvQComboBoxGuiItem::~MvQComboBoxGuiItem()
{
	delete combo_;
}

QString MvQComboBoxGuiItem::currentValue()
{
	return combo_->currentText();
} 

void  MvQComboBoxGuiItem::addValue(QString value)
{
	combo_->addItem(value);
}

MvQCheckBoxGuiItem::MvQCheckBoxGuiItem(MvRequest* r,QGridLayout *parentLayout) : MvQGuiItem(r,parentLayout)
{
	//CheckBox
	checkBox_ = new QCheckBox;
	//nameLabel_->setBuddy(checkBox_);
	
	//Add to layout
	parentLayout->addWidget(checkBox_,row_,MvQGuiItem::WidgetColumn);

	//Assign values to true and false
	const char* 	trueVal;
	r->getValue(trueVal,"true",0);
	values_[QString(trueVal)]=Qt::Checked;

	const char* 	falseVal;
	r->getValue(falseVal,"false",0);
	values_[QString(falseVal)]=Qt::Unchecked;

	const char* dval;
	r->getValue(dval,"default",0);
	default_=QString(dval);
	if(values_.contains(default_))
	{
		checkBox_->setCheckState(values_[default_]);
	}
}

MvQCheckBoxGuiItem::~MvQCheckBoxGuiItem()
{
	delete checkBox_;
}

QString MvQCheckBoxGuiItem::currentValue()
{
	QMapIterator<QString,Qt::CheckState> i(values_);
	while (i.hasNext()) 
	{
     		i.next();
     		if(i.value() == checkBox_->checkState()) 
		{
			return i.key();
		}
	}
	return default_;

} 


MvQOnOffGuiItem::MvQOnOffGuiItem(MvRequest* r,QGridLayout *parentLayout) : MvQGuiItem(r,parentLayout)
{
	//Layout to hold the radio buttons
	layout_= new QHBoxLayout;
	parentLayout->addLayout(layout_,row_,MvQGuiItem::WidgetColumn);
	//QWidget *w=new QWidget;
	//w->setLayout(hb);

	//Assign values to true and false
	const char* onVal;
	r->getValue(onVal,"true",0);
	QString strOnVal(onVal);

	if(strOnVal.isEmpty())
		strOnVal="on";

	const char* offVal;
	r->getValue(offVal,"false",0);
	QString strOffVal(offVal);

	if(strOffVal.isEmpty())
		strOffVal="off";

	//Radio buttons
	radio_[strOnVal] = new QRadioButton(strOnVal); //,w);
	radio_[strOffVal]= new QRadioButton(strOffVal); //,w);
	layout_->addWidget(radio_[strOnVal]);
	layout_->addWidget(radio_[strOffVal],1);

	const char* dval;
	r->getValue(dval,"default",0);
	default_=QString(dval);
	if(default_ == strOnVal || default_ == strOffVal)
	{
		radio_[default_]->setChecked(true);
	}
}

MvQOnOffGuiItem::~MvQOnOffGuiItem()
{
	delete layout_;
	QMapIterator<QString,QRadioButton*> i(radio_);
	while (i.hasNext()) 
	{
		i.next();
		delete i.value();
	}

}

QString MvQOnOffGuiItem::currentValue()
{
	QMapIterator<QString,QRadioButton*> i(radio_);
	while (i.hasNext()) 
	{
     		i.next();
     		if(i.value()->isChecked()) 
		{
			return i.key();
		}
	}
	return default_;

} 


MvQListGuiItem::MvQListGuiItem(MvRequest* r,QGridLayout *parentLayout) : MvQGuiItem(r,parentLayout)
{	
	//LinEdit		
	lineEdit_ = new QLineEdit;
	//nameLabel_->setBuddy(lineEdit_);
	
	parentLayout->addWidget(lineEdit_,row_,MvQGuiItem::WidgetColumn);

	//Get values
	int cnt = r->iterInit("values");
	for(int i=0; i<cnt; ++i)
	{
		const char *cpt;
		r->iterGetNextValue(cpt);
		values_ << QString(cpt);
	}				
	

	QToolButton *tb= new QToolButton;
	tb->setIcon(QApplication::style()->standardIcon(QStyle::SP_ToolBarHorizontalExtensionButton));
	tb->setCheckable(true);
	tb->setChecked(false);
	parentLayout->addWidget(tb,row_,MvQGuiItem::ExpandColumn);

	//listLayout_=new QHBoxLayout;
	//parentLayout->addWidget(list_,row+1,2);
	
	list_ = new QListWidget;
	list_->setVisible(false);

	//Populate the list with

	//Check if a source specified
	const char *source;	
	r->getValue(source,"source",0);
	if(source)
	{
		source_=QString(source);
		if(source_ == "*")
			source_.clear();
	}
	
	//If there is no source use "values" to populate the list and 
	// set lineEdit to "default"
	if(source_.isEmpty() == true) 
	{		
		//Set LineEdit to default value
		const char* dval;
		r->getValue(dval,"default",0);
		default_=QString(dval);
		int dindex=values_.indexOf(QString(dval));
		if(dindex != -1)
		{
			lineEdit_->setText(default_);
		}

		foreach(QString str,values_)
		{
			QListWidgetItem* item=new QListWidgetItem(str,list_);
			item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
			item->setCheckState(Qt::Unchecked);
		}
		if(dindex != -1)
		{
			list_->item(dindex)->setCheckState(Qt::Checked);
		}
	}

	//list_->addItems(values_);
	parentLayout->addWidget(list_,row_+1,MvQGuiItem::WidgetColumn);
	//listLayout_->addWidget(list_);

	/*QRegExp* rq = new QRegExp();
	QRegExpValidator* validator = new QRegExpValidator(lineEdit_);
	
	lineEdit_->setValidator(validator);*/


	connect(tb,SIGNAL(toggled(bool)),
		this,SLOT(slotSetVisibleList(bool)));

	connect(list_,SIGNAL(itemChanged(QListWidgetItem*)),
		this, SLOT(slotListItemChanged(QListWidgetItem*)));
}

MvQListGuiItem::~MvQListGuiItem()
{
	delete lineEdit_;
	delete list_;
}

void MvQListGuiItem::slotSetVisibleList(bool visible)
{
	list_->setVisible(visible);	
}

void MvQListGuiItem::slotListItemChanged(QListWidgetItem* item)
{
	QString text=lineEdit_->text();
	if(item->checkState() == Qt::Checked)
	{
		if(text.size()>0)
		{
			text+="/";
		}
		text+=item->data(Qt::DisplayRole).toString();
	}
	else
	{
		QString itemText=item->data(Qt::DisplayRole).toString();
		QStringList textList=text.split("/");
		int itemIndex=textList.indexOf(itemText);
		
		QString newText;
		for(int i=0;i < textList.count(); i++)
		{
			if(i != 0 && i != itemIndex)
			{
				newText+="/";
			}
			if(i != itemIndex)
			{	
				newText+=textList[i];
			}
		}
		text=newText;
	}

	lineEdit_->setText(text);

}	

void  MvQListGuiItem::addValue(QString value)
{
	QListWidgetItem* item=new QListWidgetItem(value,list_);
	item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
	item->setCheckState(Qt::Unchecked);
}

QString MvQListGuiItem::currentValue()
{
	QString text=lineEdit_->text();
	return text;
} 


MvQColourGuiItem::MvQColourGuiItem(MvRequest* r,QGridLayout *parentLayout) : MvQGuiItem(r,parentLayout)
{	
	//Color combo		
	combo_ =new QComboBox;
	
	//nameLabel_->setBuddy(combo_);
	
	//Add to layout
	parentLayout->addWidget(combo_,row_,MvQGuiItem::WidgetColumn);
}

MvQColourGuiItem::~MvQColourGuiItem()
{
	delete combo_;
}

void MvQColourGuiItem::slotLoadColourDialog(bool b)
{
	QColor col=QColorDialog::getColor();
}

QString MvQColourGuiItem::currentValue()
{
	return QString("red");
}

MvQSliderGuiItem::MvQSliderGuiItem(MvRequest* r,QGridLayout *parentLayout) : MvQGuiItem(r,parentLayout)
{
	const char *min;	
	r->getValue(min,"min",0);	
	int minVal=QString(min).toInt();
	
	const char *max;	
	r->getValue(max,"max",0);	
	int maxVal=QString(max).toInt();

	const char *step;	
	r->getValue(step,"step",0);	
	int stepVal=QString(step).toInt();

	const char *def;	
	r->getValue(def,"default",0);	
	int defVal=QString(def).toInt();

	const char *direction;	
	r->getValue(direction,"direction",0);	
	QString directionVal(direction);

	//Slider		
	slider_ =new QSlider(Qt::Horizontal);
	slider_->setMinimum(minVal);
	slider_->setMaximum(maxVal);
	slider_->setSingleStep(stepVal);
	slider_->setPageStep(stepVal);
	slider_->setTickInterval(stepVal);
	slider_->setTickPosition(QSlider::TicksBelow);
	slider_->setSliderPosition(defVal);

	//nameLabel_->setBuddy(slider_);

	//valueLabel
	valueLabel_=new QLabel;
	slotSetValueLabel(defVal);

	layout_=new QHBoxLayout;	
	layout_->addWidget(slider_);
	layout_->addWidget(valueLabel_);

	parentLayout->addLayout(layout_,row_,MvQGuiItem::WidgetColumn);

	connect(slider_, SIGNAL(valueChanged(int)), this, SLOT(slotSetValueLabel(int)) );
}

MvQSliderGuiItem::~MvQSliderGuiItem()
{
	delete layout_;
	delete slider_;
	delete valueLabel_;
}
	
void MvQSliderGuiItem::slotSetValueLabel(int value)
{
	valueLabel_->setText(QString::number(value));
}

QString MvQSliderGuiItem::currentValue()
{
	return valueLabel_->text();
}

MvQLineEditGuiItem::MvQLineEditGuiItem(MvRequest* r,QGridLayout *parentLayout,
		    MvQLineEditGuiItem::InputType type) : MvQGuiItem(r,parentLayout)
{
	type_=type;

	//LinEdit		
	lineEdit_ = new QLineEdit;
	//nameLabel_->setBuddy(lineEdit_);
	
	//Add to layout
	parentLayout->addWidget(lineEdit_,row_,MvQGuiItem::WidgetColumn);

	//Validator
	switch(type_)
	{
	case Integer:
	{
		int minVal, maxVal;

		//Min
		const char *min;	
		r->getValue(min,"min",0);
		if(min)
		{
			minVal=QString(min).toInt();
		}
		//Max
		const char *max;	
		r->getValue(max,"max",0);
		if(max)
		{
			maxVal=QString(max).toInt();
		}
		QIntValidator* validator = new QIntValidator(lineEdit_);
		if(min != 0 && max !=0)
		{
			validator->setRange(minVal,maxVal);
		}
		lineEdit_->setValidator(validator);

		break;
	}
	case Float:
	{
		float minVal, maxVal;

		//Min
		const char *min;	
		r->getValue(min,"min",0);
		if(min)
		{
			minVal=QString(min).toDouble();
		}
		//Max
		const char *max;	
		r->getValue(max,"max",0);
		if(max)
		{
			maxVal=QString(max).toDouble();
		}
		QDoubleValidator* validator = new QDoubleValidator(lineEdit_);
		if(min != 0 && max !=0)
		{
			validator->setRange(minVal,maxVal,5);
		}
		lineEdit_->setValidator(validator);

		break;
	}	


	default:
		break;
	}

	const char *def;	
	r->getValue(def,"default",0);
	if(def)
		lineEdit_->setText(QString(def));
	
}

MvQLineEditGuiItem::~MvQLineEditGuiItem()
{
	delete lineEdit_;
}

QString MvQLineEditGuiItem::currentValue()
{
	return lineEdit_->text();
}

//======================================
// TextEdit
//======================================

MvQTextEditGuiItem::MvQTextEditGuiItem(MvRequest* r,QGridLayout *parentLayout) : MvQGuiItem(r,parentLayout)
{	
	//LinEdit		
	textEdit_ = new QTextEdit;
	//nameLabel_->setBuddy(lineEdit_);

	const char *def;	
	r->getValue(def,"default",0);
	if(def)
		textEdit_->setPlainText(QString(def));
	
	//Add to layout

	parentLayout->addWidget(textEdit_,row_,MvQGuiItem::WidgetColumn);
}

MvQTextEditGuiItem::~MvQTextEditGuiItem()
{
	delete textEdit_;
}

QString MvQTextEditGuiItem::currentValue()
{
	return textEdit_->toPlainText();
}




MvQGuiItem* MvQGuiItemFactory::makeItem(MvRequest* r,QGridLayout* layout)
{
	QString type(r->getVerb());

	qDebug() << "Gui type: " << type;

	if(type == "option_menu")
  	{
		return new MvQComboBoxGuiItem(r,layout);
	}
	else if(type == "checkbox")
  	{
		return new MvQCheckBoxGuiItem(r,layout);
	}
	else if(type == "on_off")
  	{
		return new MvQOnOffGuiItem(r,layout);
	}
	else if(type == "menu")
  	{
		return new MvQListGuiItem(r,layout);
	}
	else if(type == "colour")
  	{
		return new MvQColourGuiItem(r,layout);
	}
  	else if(type == "any")
  	{
		return new MvQLineEditGuiItem(r,layout,MvQLineEditGuiItem::Text);
	}
 	else if(type == "ui_integer")
  	{
		return new MvQLineEditGuiItem(r,layout,MvQLineEditGuiItem::Integer);
	}
	else if(type == "ui_float")
  	{
		return new MvQLineEditGuiItem(r,layout,MvQLineEditGuiItem::Float);
	}
	else if(type == "slider")
  	{
		return new MvQSliderGuiItem(r,layout);
	}
	else if(type == "scrolled_text")
  	{
		return new MvQTextEditGuiItem(r,layout);
	}
	/*else if(type == "line")
    	{
		return new MvQLineEditItem;
	}*/
	return 0;
}
