/***************************** 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 <QApplication>
#include <QDebug>
#include <QHBoxLayout>  
#include <QInputDialog>
#include <QLabel>
#include <QListWidget>
#include <QProgressBar>
#include <QSettings>
#include <QSpinBox>
#include <QSplitter>
#include <QSortFilterProxyModel>
#include <QTabWidget>
#include <QTextBrowser>
#include <QToolButton>
#include <QVBoxLayout>

#include "MvApplication.h"
#include "MvRequest.h"

#include <stdlib.h>

#ifdef METVIEW_ODB_NEW
#include "MvOdb.h"
#include "odb_api/odbcapi.h"
#endif

#include "MvQAbout.h"
#include "MvQFileInfoLabel.h"
#include "MvQLogBrowser.h"
#include "MvQOdbDataWidget.h"
#include "MvQOdbMetaData.h"
#include "MvQOdbModel.h"
#include "MvQOdbTableView.h"
#include "MvQSearchLinePanel.h"
#include "MvQTreeView.h"
#include "MvQTreeViewSearchLine.h"

#include "OdbExaminer.h"


OdbExaminer::OdbExaminer(QWidget *parent) : MvQMainWindow(parent)
{
 	data_=0;
	columnFind_=0;
	tableColumnFind_=0;
 
	setAttribute(Qt::WA_DeleteOnClose);	

	setWindowTitle(tr("Metview - ODB Examiner"));

	//Initial size
	setInitialSize(1100,800);

	QWidget *w;
	QLabel *label;

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

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

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

	//-----------------------------------------------------
	// The main layout (the upper part of mainSplitter)
	//-----------------------------------------------------
  
	QVBoxLayout *mainLayout = new QVBoxLayout;
        mainLayout->setObjectName(QString::fromUtf8("vboxLayout"));
	mainLayout->setContentsMargins(0,0,0,0);
	mainLayout->setSpacing(1);
	w=new QWidget;
	w->setLayout(mainLayout);
	mainSplitter_->addWidget(w);

	//------------------
	// File info label
	//------------------
      	
	fileInfoLabel_=new MvQFileInfoLabel;
	fileInfoLabel_->setProperty("mvStyle","odb");
	mainLayout->addWidget(fileInfoLabel_);

	//-------------------
	// Central tab	
	//-------------------
		
	metaTab_= new QTabWidget;	
	mainLayout->addWidget(metaTab_,1);
	
	//Set up grib message group box
	setupTableBox();
	setupColumnBox();
	setupVarBox();
	//setupStatsBox();

	dataPanel_=new MvQOdbDataWidget(this);
	//setupDataBox();

	metaTab_->addTab(tablePanel_,tr("Tables"));
	metaTab_->addTab(columnPanel_,tr("Columns"));
	metaTab_->addTab(varPanel_,tr("SET Variables"));
	metaTab_->addTab(dataPanel_,tr("Data"));

	//Find panel
	
	//We need to call it after the tab is populated
	setupFindBox();
	mainLayout->addWidget(findPanel_);

	//--------------------------
	// Log Area
	//--------------------------

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

	//Label
	label = new QLabel(tr("Log"));
	label->setFrameShape(QFrame::StyledPanel);
	logLayout->addWidget(label);

	//Log browser
	logBrowser_= new MvQLogBrowser(logLayout);

	w->hide();

	//----------------------------
	// Signals and slots
	//----------------------------

	connect(tableView_,SIGNAL(tableSelection(QString)),
		this,SLOT(slotTableSelected(QString))); 

	connect(metaTab_,SIGNAL(currentChanged(int)),
		this,SLOT(slotTabIndexChanged(int)));

	setupEditActions();
	setupViewActions();
	setupSettingsActions();
	setupHelpActions();

	//----------------------------
	// Setup menus and toolbars
	//----------------------------

	setupMenus(menuItems_);
	
	//Should be called only after init
	//readSettings();
}
 
OdbExaminer::~OdbExaminer()
{
	writeSettings();

	/*if(columnModel_) delete columnModel_;
	if(dataModel_) delete dataModel_;
	if(bitmapModel_) delete bitmapModel_;

	for(vector<QStandardItemModel*>::iterator it=secModel_.begin(); it != secModel_.end(); it++)
	{
		delete *it;
	}*/	
}

void OdbExaminer::setupEditActions()
{
	QAction *actionFind_=MvQMainWindow::createAction(MvQMainWindow::FindAction,this);
	connect(actionFind_,SIGNAL(triggered(bool)),
		findPanel_,SLOT(setHidden(bool)));
				
	QAction *actionFindNext=MvQMainWindow::createAction(MvQMainWindow::FindNextAction,this);
	connect(actionFindNext,SIGNAL(triggered(bool)),
		findPanel_,SLOT(slotFindNext(bool)));	
		
	QAction *actionFindPrev=MvQMainWindow::createAction(MvQMainWindow::FindPreviousAction,this);
	connect(actionFindPrev,SIGNAL(triggered(bool)),
		findPanel_,SLOT(slotFindPrev(bool)));
	
	MvQMainWindow::MenuType menuType=MvQMainWindow::EditMenu;	
		
	menuItems_[menuType].push_back(new MvQMenuItem(actionFind_,MvQMenuItem::MenuTarget));
	menuItems_[menuType].push_back(new MvQMenuItem(actionFindNext,MvQMenuItem::MenuTarget));
	menuItems_[menuType].push_back(new MvQMenuItem(actionFindPrev,MvQMenuItem::MenuTarget));
}

void OdbExaminer::setupViewActions()
{
	//
	QAction* actionFileInfo = new QAction(this);
        actionFileInfo->setObjectName(QString::fromUtf8("actionFileInfo"));
	actionFileInfo->setText(tr("File info"));
	actionFileInfo->setCheckable(true);
	actionFileInfo->setChecked(true);
	actionFileInfo->setToolTip(tr("View file info"));
	QIcon icon;
	icon.addPixmap(QPixmap(QString::fromUtf8(":/examiner/fileInfo.svg")), QIcon::Normal, QIcon::Off);
 	actionFileInfo->setIcon(icon);	
	
	//Define routines
	connect(actionFileInfo,SIGNAL(triggered(bool)),
		fileInfoLabel_,SLOT(setVisible(bool)));

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

void OdbExaminer::setupSettingsActions()
{
	QAction *action;
	
	action=createAction(MvQMainWindow::ConfigureAction,this);
	connect(action, SIGNAL(triggered()), 
		this, SLOT(slotConfigure()));	
			
	MvQMainWindow::MenuType menuType=MvQMainWindow::SettingsMenu;
	menuItems_[menuType].push_back(new MvQMenuItem(action,MvQMenuItem::MenuTarget));
}

void OdbExaminer::setupHelpActions()
{		
    	// About
    	QAction *actionAbout = new QAction(this);
    	actionAbout->setObjectName(QString::fromUtf8("actionAbout"));
    	QIcon icon;
    	icon.addPixmap(QPixmap(QString::fromUtf8(":/window/metview_logo")), QIcon::Normal, QIcon::Off);
    	actionAbout->setIcon(icon);
    	actionAbout->setText(tr("&About ODB Examiner"));

	connect(actionAbout, SIGNAL(triggered()), this, SLOT(slotShowAboutBox()));

	MvQMainWindow::MenuType menuType=MvQMainWindow::HelpMenu;
	menuItems_[menuType ].push_back(new MvQMenuItem(actionAbout,MvQMenuItem::MenuTarget));
}

void OdbExaminer::setupTableBox()
{
	//--------------------------------
	// Message tree (key profile)
	//--------------------------------

	tablePanel_=new QWidget;
	QVBoxLayout *tableLayout = new QVBoxLayout;
	tableLayout->setContentsMargins(0,0,0,0);
	tablePanel_->setLayout(tableLayout);
	//messageSplitter_->addWidget(messageWidget);	

	//Label
	//label=new QLabel(tr("Tables"));
	//label->setFrameShape(QFrame::StyledPanel);
	//label->setProperty("mvStyle","panel");
	//QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
       // sizePolicy.setHorizontalStretch(0);
       // sizePolicy.setVerticalStretch(0);
      //  sizePolicy.setHeightForWidth(label->sizePolicy().hasHeightForWidth());
        //label->setSizePolicy(sizePolicy);
	//tableLayout->addWidget(label);

	//Hbox
	tableSplitter_=new QSplitter;
	tableLayout->addWidget(tableSplitter_);	

	//Table view
	tableView_=new MvQOdbTableView;
	tableSplitter_->addWidget(tableView_);	

	//Column tree
	tableColumnModel_= new MvQOdbColumnModel(false);
	tableColumnSortModel_= new QSortFilterProxyModel;
        tableColumnSortModel_->setSourceModel(tableColumnModel_);
	tableColumnSortModel_->setDynamicSortFilter(true);
	//columnSortModel_->setFilterRole(Qt::UserRole);
	//columnSortModel_->setFilterRegExp(QRegExp("[1]"));
	//columnSortModel_->setFilterFixedString("1");
	//columnSortModel_->setFilterKeyColumn(0);


	tableColumnTree_=new QTreeView;
	tableColumnTree_->setObjectName("columnTree");
	tableColumnTree_->setProperty("mvStyle",0);
	tableColumnTree_->setSortingEnabled(true); 
	tableColumnTree_->sortByColumn (0,Qt::AscendingOrder); 
	tableColumnTree_->setAlternatingRowColors(true);
        tableColumnTree_->setAllColumnsShowFocus(true);
	tableColumnTree_->setModel(tableColumnSortModel_);	
	//columnTree_->header()->setContextMenuPolicy(Qt::CustomContextMenu);
	//columnTree_->setActvatedByKeyNavigation(true);
	//columnTree_->setAcceptDrops(true);
	//columnTree_->setDragDropMode(QAbstractItemView::DropOnly);
	tableColumnTree_->setRootIsDecorated(true);

	tableSplitter_->addWidget(tableColumnTree_);

}

void OdbExaminer::setupColumnBox()
{
	//--------------------------------
	// Message tree (key profile)
	//--------------------------------

	columnPanel_=new QWidget;
	QVBoxLayout *columnLayout = new QVBoxLayout;
	columnLayout->setContentsMargins(0,0,0,0);
	columnPanel_->setLayout(columnLayout);
	//messageSplitter_->addWidget(messageWidget);	

	//Label
	//label=new QLabel(tr("Columns"));
	//label->setFrameShape(QFrame::StyledPanel);
	//label->setProperty("mvStyle","panel");
	//columnLayout->addWidget(label);

	//Column tree
	columnModel_= new MvQOdbColumnModel(true);
	columnSortModel_= new QSortFilterProxyModel;
        columnSortModel_->setSourceModel(columnModel_);
	columnSortModel_->setDynamicSortFilter(true);
	//columnSortModel_->setFilterRole(Qt::UserRole);
	//columnSortModel_->setFilterRegExp(QRegExp("[1]"));
	//columnSortModel_->setFilterFixedString("1");
	//columnSortModel_->setFilterKeyColumn(0);


	columnTree_=new QTreeView;
	columnTree_->setObjectName("columnTree");
	columnTree_->setProperty("mvStyle",0);
	columnTree_->setSortingEnabled(true); 
	columnTree_->sortByColumn (0,Qt::AscendingOrder); 
	columnTree_->setAlternatingRowColors(true);
        columnTree_->setAllColumnsShowFocus(true);
	columnTree_->setModel(columnSortModel_);	
	//columnTree_->header()->setContextMenuPolicy(Qt::CustomContextMenu);
	//columnTree_->setActvatedByKeyNavigation(true);
	//columnTree_->setAcceptDrops(true);
	//columnTree_->setDragDropMode(QAbstractItemView::DropOnly);
	//columnTree_->setRootIsDecorated(false);

	columnLayout->addWidget(columnTree_);
	
}

void OdbExaminer::setupVarBox()
{
	//--------------------------------
	// Message tree (key profile)
	//--------------------------------

	varPanel_=new QWidget;
	QVBoxLayout *varLayout = new QVBoxLayout;
	varLayout->setContentsMargins(0,0,0,0);
	varPanel_->setLayout(varLayout);
	//messageSplitter_->addWidget(messageWidget);	

	//Label
	//label=new QLabel(tr("SET variables"));
	//label->setFrameShape(QFrame::StyledPanel);
	//label->setProperty("mvStyle","panel");
	//varLayout->addWidget(label);

	//Var tree
	varModel_= new MvQOdbVarModel;
	varSortModel_= new QSortFilterProxyModel;
        varSortModel_->setSourceModel(varModel_);
	varSortModel_->setDynamicSortFilter(true);
	
	varTree_=new QTreeView;
	varTree_->setObjectName("varTree");
	varTree_->setProperty("mvStyle",0);
	varTree_->setSortingEnabled(true); 
	varTree_->sortByColumn (0,Qt::AscendingOrder); 
	varTree_->setAlternatingRowColors(true);
        varTree_->setAllColumnsShowFocus(true);
	varTree_->setModel(varSortModel_);	
	//varTree_->header()->setContextMenuPolicy(Qt::CustomContextMenu);
	//varTree_->setActvatedByKeyNavigation(true);
	//varTree_->setAcceptDrops(true);
	//varTree_->setDragDropMode(QAbstractItemView::DropOnly);
	varTree_->setRootIsDecorated(false);

	varLayout->addWidget(varTree_);

}

void OdbExaminer::setupFindBox()
{	
	findPanel_=new MvQSearchLinePanel;
	
	columnFind_= new MvQTreeViewSearchLine(columnTree_,0,"");
	findPanel_->addSearchLine(columnFind_,columnTree_);
	
	tableColumnFind_= new MvQTreeViewSearchLine(tableColumnTree_,0,"");
	findPanel_->addSearchLine(tableColumnFind_,columnTree_);
	
	findPanel_->hide(); 
}

void OdbExaminer::init(MvQOdbMetaData *data)
{	
	//Set bufr metadata object
	data_=data;

	//It is using the ODB version!!!
	readSettings();
		
	if(data_->odbVersion() == MvQOdbMetaData::Version1)
	{
		tableView_->init(data_,"hdr");

		columnModel_->setData(data_->columns(),data_->odbVersion());
		for(int i=0;i < columnModel_->columnCount()-1; i++)
		{ 
			columnTree_->resizeColumnToContents(i);
		}

		varModel_->setData(data_->vars());
		for(int i=0;i < varModel_->columnCount()-1; i++)
		{ 
			varTree_->resizeColumnToContents(i);
		}
		
		metaTab_->setTabEnabled(3,false);
				
		columnFind_= new MvQTreeViewSearchLine(columnTree_,0,"");
		findPanel_->addSearchLine(columnFind_,metaTab_->widget(1));
	
		tableColumnFind_= new MvQTreeViewSearchLine(tableColumnTree_,0,"");
		findPanel_->addSearchLine(tableColumnFind_,metaTab_->widget(0));
		
		varFind_= new MvQTreeViewSearchLine(varTree_,0,"");
		findPanel_->addSearchLine(varFind_,metaTab_->widget(2));
	}
	else if(data_->odbVersion() == MvQOdbMetaData::Version2)
	{
		metaTab_->setTabEnabled(0,false);
		metaTab_->setTabEnabled(1,true);
		metaTab_->setTabEnabled(2,false);	
	
		qDebug() << "examiner columns" << data_->columns().count() << data_->columnNum();

		columnModel_->setData(data_->columns(),data->odbVersion());
		for(int i=0;i < columnModel_->columnCount()-1; i++)
		{ 
			columnTree_->resizeColumnToContents(i);
		}

		columnFind_= new MvQTreeViewSearchLine(columnTree_,0,"");
		findPanel_->addSearchLine(columnFind_,metaTab_->widget(1));

		dataFind_= new MvQTreeViewSearchLine(dataPanel_->dataTree(),0,"");
		findPanel_->addSearchLine(dataFind_,metaTab_->widget(4));		
		
		metaTab_->setCurrentIndex(1);
	}	
	
	//Fileinfo label
	updateFileInfoLabel();
		
	//-----------------------
	// Data
	//-----------------------
	//Data tab is initialised when we first click on it!!
	
	//It is using the ODB version so has to be called here!!!
	readSettings();
		
}


void OdbExaminer::slotTableSelected(QString tableName)
{
	MvQOdbTable *table=data_->tables()[tableName];
	tableColumnModel_->setData(table->columns(),data_->odbVersion());
	for(int i=0;i < tableColumnModel_->columnCount()-1; i++)
	{ 
		tableColumnTree_->resizeColumnToContents(i);
	}

}

void OdbExaminer::slotTabIndexChanged(int index)
{
	if(index == 3)
	{
		if(data_)
		{
			if(!dataPanel_->initialised() && 
			   !dataPanel_->init(data_->path()))
			{
				metaTab_->setTabEnabled(3,false);
			}
		}
		else
		{
			metaTab_->setTabEnabled(3,false);
		}
	}
	
	findPanel_->setCurrentSearchLineById(metaTab_->currentWidget());
}

void OdbExaminer::slotShowAboutBox()
{
	const char *odbapi_version = odb_api_version();
	QString odbapiVersion(odbapi_version);

	QMap<MvQAbout::Version,QString> text;
	text[MvQAbout::OdbApiVersion]=odbapiVersion;	

	MvQAbout about("ODB Examiner","",MvQAbout::MetviewVersion | MvQAbout::OdbApiVersion,text);
	about.exec();
}

void OdbExaminer::slotConfigure()
{
	if(data_ && data_->odbVersion() != MvQOdbMetaData::Version2)
		return;
	
	bool ok;
     	int maxSize = QInputDialog::getInt(0, tr("Configure"),
                                          tr("Maximum size of data blocks (MB):"), 
                                          dataPanel_->maxChunkSizeInMb(),1,2000,1,&ok);
	if(ok)
        {
	 	dataPanel_->setMaxChunkSizeInMb(maxSize);
	}
}

void OdbExaminer::loadStarted()
{
	QApplication::setOverrideCursor(QCursor(Qt::BusyCursor));

	//loadProgress_->setRange(0,0);
	//loadProgress_->show();
}

void OdbExaminer::loadFinished()
{
	QApplication::restoreOverrideCursor();

	//loadProgress_->hide();
	//loadProgress_->setRange(0,1);
	//loadProgress_->setValue(1);	
}

void OdbExaminer::updateFileInfoLabel()
{
	fileInfoLabel_->setOdbTextLabel(data_->path(),data_->odbVersionString());
}

void OdbExaminer::writeSettings()
{
	if(!data_)
		return;
		
	QSettings settings("ECMWF","MV4-OdbExaminer");
	
	if(data_->odbVersion() == MvQOdbMetaData::Version1)
	{
		settings.beginGroup("mainWindow_version1");
		settings.setValue("geometry",saveGeometry());
		settings.setValue("mainSplitter",mainSplitter_->saveState());
		//settings.setValue("bottomSplitter",bottomSplitter->saveState());
		settings.endGroup();
	}
	else if(data_->odbVersion() == MvQOdbMetaData::Version2)
	{
		settings.beginGroup("mainWindow_version2");
		settings.setValue("geometry",saveGeometry());
		settings.setValue("mainSplitter",mainSplitter_->saveState());
		settings.endGroup();
	}
	
	settings.beginGroup("global");
	settings.setValue("maxChunkSizeInMb",dataPanel_->maxChunkSizeInMb());
	settings.endGroup();
}

void OdbExaminer::readSettings()
{
	if(!data_)
		return;

	QSettings settings("ECMWF","MV4-OdbExaminer");
	
	if(data_->odbVersion() == MvQOdbMetaData::Version1)
	{	
		settings.beginGroup("mainWindow_version1");
		restoreGeometry(settings.value("geometry").toByteArray());
		mainSplitter_->restoreState(settings.value("mainSplitter").toByteArray());
		//bottomSplitter->restoreState(settings.value("bottomSplitter").toByteArray());
		settings.endGroup();
	}
	else if(data_->odbVersion() == MvQOdbMetaData::Version2)
	{	
		settings.beginGroup("mainWindow_version2");
		restoreGeometry(settings.value("geometry").toByteArray());
		mainSplitter_->restoreState(settings.value("mainSplitter").toByteArray());
		//bottomSplitter->restoreState(settings.value("bottomSplitter").toByteArray());
		settings.endGroup();
	}
	
	settings.beginGroup("global");
	if(!settings.value("maxChunkSizeInMb").isNull())
	{
		dataPanel_->setMaxChunkSizeInMb(settings.value("maxChunkSizeInMb").toInt());
	}
	settings.endGroup();

}
