/***************************** 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 <QAction>
#include <QComboBox>
#include <QDebug>
#include <QHBoxLayout>
#include <QInputDialog>
#include <QLabel>
#include <QListWidget>
#include <QPlainTextEdit>
#include <QProgressBar>
#include <QPushButton>
#include <QSettings>
#include <QSplitter>
#include <QStatusBar>
#include <QTabWidget>
#include <QTreeWidget>
#include <QVBoxLayout>

#include "MvQMarsBrowser.h"

#include "LogHandler.h"
#include "MvQAbout.h"
#include "MvQLogBrowser.h"
#include "MvQMarsCatalog.h"

MvQMarsBrowser::MvQMarsBrowser(QWidget *parent) : MvQMainWindow(parent)
{
	data_ = new MvQMarsCatalogData;
	catalog_= new MvQMarsCatalog;
	
	setAttribute(Qt::WA_DeleteOnClose);	

	setWindowTitle(tr("Metview - MARS Catalogue Browser"));

	//Initial size
	setInitialSize(800,600);

	//----------------------
	// Main splitter
	//----------------------

	mainSplitter_= new QSplitter;
	mainSplitter_->setOrientation(Qt::Vertical);

        mainSplitter_->setOpaqueResize(false);
	setCentralWidget(mainSplitter_);

	//-----------------------------------------------------
	// Tabs (the upper part of mainSplitter)
	//-----------------------------------------------------

	QVBoxLayout *mainLayout = new QVBoxLayout;
        mainLayout->setObjectName(QString::fromUtf8("vboxLayout"));
	mainLayout->setContentsMargins(0,0,0,0);
	mainLayout->setSpacing(1);
	
	QWidget *w=new QWidget;
	w->setLayout(mainLayout);
	mainSplitter_->addWidget(w);
		
 	mainTab_ = new QTabWidget;	
  	mainLayout->addWidget(mainTab_);

	//-----------------------------------------------------
	// Tab: navigate 
	//----------------------------------------------------- 	

	/*QVBoxLayout *mainLayout = new QVBoxLayout;
        mainLayout->setObjectName(QString::fromUtf8("vboxLayout"));
	mainLayout->setContentsMargins(0,0,0,0);
	mainLayout->setSpacing(1);
	
	QWidget *w=new QWidget;
	w->setLayout(mainLayout);
	mainTab_->addTab(w,tr("Navigate"));*/

	w=new QWidget;
	QVBoxLayout *navLayout=new QVBoxLayout;
	w->setLayout(navLayout);
	mainTab_->addTab(w,tr("Navigate"));
	
	centralSplitter_ = new QSplitter(this); 
	centralSplitter_->setOpaqueResize(false);	
	navLayout->addWidget(centralSplitter_);
	//mainLayout->addWidget(centralSplitter_);
	
	nodeTree_=new QTreeWidget;
	nodeTree_->setColumnCount(2);
	nodeTree_->setRootIsDecorated(false);
	nodeTree_->setUniformRowHeights(true);
	nodeTree_->setProperty("mvStyle",0);
	nodeTree_->setAlternatingRowColors(true);
	
	centralSplitter_->addWidget(nodeTree_);
	QStringList headers;
	headers << tr("Parameter") << tr("Selection");
	nodeTree_->setHeaderLabels(headers);
		
	itemList_ = new QListWidget;
	itemList_->setUniformItemSizes(true);
	itemList_->setProperty("mvStyle",1);
	itemList_->setAlternatingRowColors(true);
	centralSplitter_->addWidget(itemList_);
	
	//axis
	axisLayout_ = new QHBoxLayout;
	navLayout->addLayout(axisLayout_);
	
	//-----------------------------------------------------
	// Tab: Request
	//----------------------------------------------------- 	

	requestTe_= new QPlainTextEdit;
	requestTe_->setLineWrapMode(QPlainTextEdit::NoWrap);
	mainTab_->addTab(requestTe_,tr("Request"));
	
	macroTe_= new QPlainTextEdit;
	macroTe_->setLineWrapMode(QPlainTextEdit::NoWrap);
	mainTab_->addTab(macroTe_,tr("Macro"));

	//-------------------------------------------------------
	// Push buttons
	//-------------------------------------------------------

	/*QHBoxLayout *pbLayout=new QHBoxLayout;
	mainLayout->addLayout(pbLayout);
	
	QPushButton *pb=new QPushButton(tr("Create MARS Retrieval icon"),this);
	mainLayout->addWidget(pb);*/
	
	//--------------------------
	// Log Area
	//--------------------------

	QVBoxLayout *logLayout = new QVBoxLayout;
        logLayout->setObjectName(QString::fromUtf8("vboxLayout"));
	logLayout->setContentsMargins(0,0,0,0);
	
	logPanel_=new QWidget;
	logPanel_->setMinimumHeight(110);
	logPanel_->setLayout(logLayout);

	QHBoxLayout *hb = new QHBoxLayout;
	hb->setContentsMargins(0,0,0,0);
	logLayout->addLayout(hb);	
	
	//Label
	QLabel *label = new QLabel(tr("Log"));
	label->setFrameShape(QFrame::StyledPanel);
	hb->addWidget(label,1);
	
	//Clear button
	QPushButton *clearPb = new QPushButton(tr("Clear log"));
	hb->addWidget(clearPb);
	
	//Log browser
	logBrowser_= new MvQLogBrowser(logLayout);

	connect(clearPb,SIGNAL(clicked(bool)),
		this,SLOT(slotClearLog(bool)));
		
	mainSplitter_->addWidget(logPanel_);
	mainSplitter_->setCollapsible(1,false);

	//-------------------
	// Statusbar
	//-------------------

	loadProgress_=new QProgressBar;
	loadProgress_->setRange(0,0);
	statusBar()->addPermanentWidget(loadProgress_);
	loadProgress_->hide();
	
 	statusMessageLabel_ = new QLabel("");
    	statusMessageLabel_->setFrameShape(QFrame::NoFrame);
    	statusBar()->addPermanentWidget(statusMessageLabel_,1);  // '1' means 'please stretch me when 	
	
	//----------------------------
	// Signals and slots
	//----------------------------
		
	connect(catalog_,SIGNAL(fetchFinished(QString,bool)),
		this,SLOT(slotFetchFinished(QString,bool)));
		
	//connect(nodeTree_,SIGNAL(itemClicked(QTreeWidgetItem*,int)),
	//	this,SLOT(slotNodeSelected(QTreeWidgetItem*,int)));
	
	connect(nodeTree_,SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
		this,SLOT(slotNodeSelected(QTreeWidgetItem*,QTreeWidgetItem*)));

	connect(itemList_,SIGNAL(itemClicked(QListWidgetItem *)),
		this,SLOT(slotValueSelected(QListWidgetItem *)));

	connect(catalog_,SIGNAL(statusMessage(QString)),
		statusMessageLabel_,SLOT(setText(QString)));

	connect(catalog_,SIGNAL(logUpdated()),
		this,SLOT(slotUpdateLogOutput()));	
		
	setupViewActions();
	setupControlsActions();
	setupHelpActions();
	
	setupMenus(menuItems_);
	
	//Initialise
	init();
	
	readSettings();
} 

MvQMarsBrowser::~MvQMarsBrowser()
{
  	writeSettings();
}


void MvQMarsBrowser::setupViewActions()
{	
  	actionLog_=createAction(MvQMainWindow::LogAction,this);
		
	connect(actionLog_,SIGNAL(toggled(bool)),
		logPanel_,SLOT(setVisible(bool)));
		
	logPanel_->hide();

	MvQMainWindow::MenuType menuType=MvQMainWindow::ViewMenu;
	menuItems_[menuType].push_back(new MvQMenuItem(actionLog_));	
}

void MvQMarsBrowser::setupControlsActions()
{
	//Combo box
	//We will add items + signal/slots later in "init"!
	QHBoxLayout *hb=new  QHBoxLayout;

	//Combo box for database
	QLabel *dbLabel = new QLabel(tr("Database:"));
	dbCombo_ = new QComboBox;
	dbLabel->setBuddy(dbCombo_);

	hb->addWidget(dbLabel);
	hb->addWidget(dbCombo_);
	QWidget* wh=new QWidget;
	wh->setLayout(hb);

	//Create retrieval icon
	QAction *iconAction = new QAction(this);
	iconAction->setObjectName(QString::fromUtf8("actionCreate")); 
    	iconAction->setIcon(QIcon(QPixmap(QString::fromUtf8(":/mars/create_mars.svg"))));
	
	iconAction->setText("&Create icon");
	iconAction->setToolTip(tr("Create MARS Rertieval icon"));

	connect(iconAction, SIGNAL(triggered()), 
		this, SLOT(slotCreateMarsIcon()));
		
	//MvQMenuItem::MenuTarget
	MvQMainWindow::MenuType menuType=MvQMainWindow::SettingsMenu;
	menuItems_[menuType].push_back(new MvQMenuItem(wh));
	menuItems_[menuType].push_back(new MvQMenuItem(iconAction));
}

void MvQMarsBrowser::setupHelpActions()
{			
	QAction *action;
	
	action=createAction(MvQMainWindow::AboutAction,this);
	action->setText(tr("About MARS Catalog Browser"));
	connect(action, SIGNAL(triggered()), 
		this, SLOT(slotShowAboutBox()));	
		
	MvQMainWindow::MenuType menuType=MvQMainWindow::HelpMenu;
	menuItems_[menuType].push_back(new MvQMenuItem(action,MvQMenuItem::MenuTarget));	
}

void MvQMarsBrowser::init()
{
  	//Init db combo
   	//int currentIndex=0;
	dbCombo_->addItem("ERA");
	
	//keyCombo_->setCurrentIndex(-1);
	
	//connect(keyCombo_, SIGNAL(currentIndexChanged(int)),  
	//	this,SLOT(slotLoadKeyProfile(int))); 
	
	//Fetch data
	fetch();
}  

void MvQMarsBrowser::reset()
{
	data_->clear();
	data_->init();
	updateUi();
}

void MvQMarsBrowser::updateUi()
{
  	nodeTree_->clear();
 	itemList_->clear();
	
	QTreeWidgetItem *currentItem=0;	
  	QList<QTreeWidgetItem *> items;
	foreach(MvQMarsCatalogNode* node, data_->data())
	{
		//qDebug() << "node" <<  node->name();
		QTreeWidgetItem *item=new QTreeWidgetItem;
		item->setData(0,Qt::DisplayRole,node->name());
		item->setData(1,Qt::DisplayRole,node->selection());
		items << item;
	
		if(node->isAxis())
		{  
			item->setData(0,Qt::ForegroundRole,Qt::red);
			item->setData(1,Qt::ForegroundRole,Qt::red);
			
			createAxisWidget(node);
		}		
		currentItem=item;
	}
		
	nodeTree_->insertTopLevelItems(0,items); 
	nodeTree_->setCurrentItem(currentItem,0);
	
	requestTe_->setPlainText(data_->catalogPathToRequest());
	macroTe_->setPlainText(data_->catalogPathToMacro());
	
	
	
}

void MvQMarsBrowser::fetchStarted()
{
	loadProgress_->setRange(0,0);
	loadProgress_->show();
}

void MvQMarsBrowser::fetchFinished()
{
	loadProgress_->hide();
	loadProgress_->setRange(0,1);
	loadProgress_->setValue(1);
}

void MvQMarsBrowser::fetch()
{
  	//fetchStarted();
	catalog_->fetch(data_);  
}  
  
void MvQMarsBrowser::slotFetchFinished(QString str,bool status)
{
 	//fetchFinished();

	if(!status)
	{  
		reset();
		return;
	}	
	
	data_->update(str);
	updateUi();	
	
	
	
	QTreeWidgetItem* nodeItem=nodeTree_->currentItem();	
	if(!nodeItem)
	  	return;
 
	QString nodeName=nodeItem->data(0,Qt::DisplayRole).toString();  
	MvQMarsCatalogNode* node=data_->node(nodeName);
	
	if(node->isAxis() == false && 
	   itemList_->count() == 1)
	{
		slotValueSelected(itemList_->item(0));	
	}
	
}  

//"{"class" : "mc","expver" : "0099","stream" : "oper","type" : "ef","year" : "2010","month" : "jul","levtype" : "sfc"}" 

void MvQMarsBrowser::slotNodeSelected(QTreeWidgetItem* item,int /*column*/)
{
	if(!item) return;
  
  	QString name=item->data(0,Qt::DisplayRole).toString();  
  	MvQMarsCatalogNode* node=data_->node(name);
	if(node)
	{
		/*if(data_->data().count() == 1 &&
		  node->name() == "class" && 
		  node->items().count() == 0)
		{
		  	fetch();
			return;
		}*/
		
		itemList_->clear();
		itemList_->insertItems(0,node->items());
		if(node->isAxis())
		{
		  	QStringList lst=node->selection().split("/");
		  	for(int i=0; i < itemList_->count(); i++)
			{
			  	QListWidgetItem *item=itemList_->item(i);
				item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsSelectable |Qt::ItemIsEnabled);
				if(lst.indexOf(item->text()) != -1)
				{  
					item->setCheckState(Qt::Checked);
				}
				else
				{  
					item->setCheckState(Qt::Unchecked);
				}	
			}
		}	
				
		itemList_->setCurrentRow(node->selectionIndex());

		qDebug() << "node" << node->name() << node->items();
		
		/*if(node->isAxis() == false && 
		   node->items().count() == 0)
		{
			slotValueSelected(itemList_[0]);	
		}*/
	}
}	

void MvQMarsBrowser::slotNodeSelected(QTreeWidgetItem* current,QTreeWidgetItem* /*next*/)
{
	slotNodeSelected(current,0);
}	

void MvQMarsBrowser::slotValueSelected(QListWidgetItem *item)
{	
  	if(catalog_->isFetchRunning())
		return;
	
 	QTreeWidgetItem* nodeItem=nodeTree_->currentItem();	
	if(!nodeItem)
	  	return;
 
	QString nodeName=nodeItem->data(0,Qt::DisplayRole).toString();  
	MvQMarsCatalogNode* node=data_->node(nodeName);
	
	if(node)
	{  	
		if(node->isAxis())
		{
  			QStringList lst;
		  	for(int i=0; i < itemList_->count(); i++)
			{
			  	if(itemList_->item(i)->checkState() == Qt::Checked)
			  	{
			    		lst << itemList_->item(i)->text();
				}
			}
			
			QString value=lst.join("/");	
  			nodeItem->setData(1,Qt::DisplayRole,value);
			node->setSelection(value);
			requestTe_->setPlainText(data_->catalogPathToRequest());
			macroTe_->setPlainText(data_->catalogPathToMacro());
		}
		else
		{
  			QString value=item->text();	
			node->setSelection(value);
			fetch();
		}
	}
}

void MvQMarsBrowser::createAxisWidget(MvQMarsCatalogNode* node)
{
 	if(!node->isAxis())
	return;
	
	QWidget *w=new QWidget(this);
	QVBoxLayout *vb=new QVBoxLayout;
	w->setLayout(vb);
	
	QLabel *label=new QLabel(node->name(),w);
	vb->addWidget(label);
	
	QListWidget *aw=new QListWidget;
	aw->setUniformItemSizes(true);
	aw->setProperty("mvStyle",1);
	aw->setAlternatingRowColors(true);
	aw->insertItems(0,node->items());
	QStringList lst=node->selection().split("/");
	for(int i=0; i < aw->count(); i++)
	{
		QListWidgetItem *item=aw->item(i);
		item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsSelectable |Qt::ItemIsEnabled);
		if(lst.indexOf(item->text()) != -1)
		{  
			item->setCheckState(Qt::Checked);
		}
		else
		{  
			item->setCheckState(Qt::Unchecked);
		}	
	}
	vb->addWidget(aw,1);	
	axisList_ << aw;
			
	axisLayout_->addWidget(w);
}

			
void MvQMarsBrowser::slotCreateMarsIcon()
{
  	bool ok;
     	QString text = QInputDialog::getText(0, tr("Create icon"),
                                          tr("Icon name:"), QLineEdit::Normal,
                                          "", &ok);
	if(ok && !text.isEmpty())
        {
	 	//MvKeyProfile *prof=keyManager_->addProfile(text.toStdString());		
		//keyCombo_->addItem(text);
		//keyCombo_->setCurrentIndex(keyCombo_->count()-1);
		//actionSave_->setEnabled(false);
	}
}


void MvQMarsBrowser::slotShowAboutBox()
{
	MvQAbout about("MARS Catalog Browser","",MvQAbout::MetviewVersion );
}

void MvQMarsBrowser::slotUpdateLogOutput()
{
	logBrowser_->update();
}

void MvQMarsBrowser::slotClearLog(bool)
{
	LogHandler::instance()->clear();
	logBrowser_->clear();
}

void MvQMarsBrowser::writeSettings()
{
	QSettings settings("ECMWF","MV4-MvQMarsBrowser");
	
	settings.beginGroup("mainWindow");
	settings.setValue("geometry",saveGeometry());
	settings.setValue("centralSplitter",centralSplitter_->saveState());
	settings.setValue("mainSplitter",mainSplitter_->saveState());
	settings.setValue("actionLogStatus",actionLog_->isChecked());		
	settings.endGroup();	
}

void MvQMarsBrowser::readSettings()
{
	QVariant value;

	QSettings settings("ECMWF","MV4-MvQMarsBrowser");
	
	settings.beginGroup("mainWindow");
	restoreGeometry(settings.value("geometry").toByteArray());
	centralSplitter_->restoreState(settings.value("centralSplitter").toByteArray());
	mainSplitter_->restoreState(settings.value("mainSplitter").toByteArray());

	if(settings.value("actionLogStatus").isNull())
	{
		actionLog_->setChecked(false);
	}
	else
	{
		actionLog_->setChecked(settings.value("actionLogStatus").toBool());
	}
	
	settings.endGroup();
}

