/***************************** 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 <QApplication>
#include <QAction>
#include <QButtonGroup>
#include <QCloseEvent>
#include <QComboBox>
#include <QCursor>
#include <QDebug>
#include <QFile>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QSettings>
#include <QSpinBox>
#include <QSplitter>
#include <QStackedWidget>
#include <QStatusBar>
#include <QString>
#include <QStringList>
#include <QTabBar>
#include <QTextBrowser>
#include <QToolButton>
#include <QVBoxLayout>

#include "GribExaminer.h"

#include "GribMetaData.h"
#include "MvKeyProfile.h"

#include "MvQAbout.h"
#include "MvQArrowSpinWidget.h"
#include "MvQFileInfoLabel.h"
#include "MvQFileListWidget.h"
#include "MvQGribDumpModel.h"
#include "MvQKeyProfileModel.h"
#include "MvQKeyProfileTree.h"
#include "MvQLogPanel.h"
#include "MvQMethods.h"
//#include "MvQTextEditSearchLine.h"
#include "MvQTreeView.h"
#include "MvQTreeExpandState.h"
//#include "MvQTreeViewSearchLine.h"

#include "MessageControlPanel.h"
#include "PlainTextWidget.h"
#include "StatusMsgHandler.h"

//===========================================================
//
// MvQGribMainPanel
//
//===========================================================

MvQGribMainPanel::MvQGribMainPanel(QWidget* parent) : QWidget(parent), data_(0)
{
    messagePanel_=new MvQMessagePanel(this);
    dumpPanel_=new MvQGribDumpPanel(this);
    gotoPanel_=new MessageControlPanel(false,false,this);

    QVBoxLayout *dataLayout=new QVBoxLayout(this);
    dataLayout->setContentsMargins(0,0,0,0);
    dataLayout->setSpacing(0);
    dataLayout->addWidget(gotoPanel_);

    dataSplitter_= new QSplitter(this);
    dataSplitter_->setOrientation(Qt::Horizontal);
    dataSplitter_->setOpaqueResize(false);
    dataLayout->addWidget(dataSplitter_,1);

    //dataSplitter_->addWidget(filterPanel_);
    dataSplitter_->addWidget(messagePanel_);
    dataSplitter_->addWidget(dumpPanel_);

    connect(messagePanel_,SIGNAL(keyProfileChanged()),
            this,SIGNAL(keyProfileChanged()));

    connect(messagePanel_,SIGNAL(messageSelected(int)),
            this,SLOT(messageSelected(int)));

    connect(gotoPanel_,SIGNAL(messageChanged(int)),
            this,SLOT(messageChangedInGoto(int)));

}

void MvQGribMainPanel::init(GribMetaData* data)
{
    Q_ASSERT(!data_);
    data_=data;

    gotoPanel_->resetMessageNum(0,false);

    messagePanel_->init(data_);
    dumpPanel_->init(data_);
}

void MvQGribMainPanel::clear()
{

}

MvKeyProfile* MvQGribMainPanel::keyProfile() const
{
    return messagePanel_->keyProfile();
}

void MvQGribMainPanel::loadKeyProfile(MvKeyProfile* prof)
{
    messagePanel_->loadKeyProfile(prof);
}


void MvQGribMainPanel::reloadData()
{
    gotoPanel_->resetMessageNum(0,false);
    messagePanel_->adjustProfile(true,-1);
}

void MvQGribMainPanel::messageChangedInGoto(int value)
{
    QApplication::setOverrideCursor(QCursor(Qt::BusyCursor));
    messagePanel_->selectMessage(value-1);
    QApplication::restoreOverrideCursor();
}

//msgCnt: starts at 0
void MvQGribMainPanel::messageSelected(int msgCnt)
{
    emit newMessageSelected();

    //The message counter might not have been initialised. But at this point
    //we must know the correct message num so we can set the counter.
    if(gotoPanel_->messageValue() == 0)
       gotoPanel_->resetMessageNum(data_->messageNum(),false);

    //Set the message counter
    gotoPanel_->setMessageValue(msgCnt+1,false);

    QApplication::setOverrideCursor(QCursor(Qt::BusyCursor));
    dumpPanel_->loadDumps(msgCnt);
    QApplication::restoreOverrideCursor();
}

void MvQGribMainPanel::writeSettings(QSettings& settings)
{
    settings.beginGroup("mainPanel");
    settings.setValue("dataSplitter",dataSplitter_->saveState());

    dumpPanel_->writeSettings(settings);
    settings.endGroup();
}

void MvQGribMainPanel::readSettings(QSettings& settings)
{
    settings.beginGroup("mainPanel");
    if(settings.contains("dataSplitter"))
    {
        dataSplitter_->restoreState(settings.value("dataSplitter").toByteArray());
    }

    dumpPanel_->readSettings(settings);
    settings.endGroup();
}


//===========================================================
//
// MvQGribDumpPanel
//
//===========================================================

MvQGribDumpPanel::MvQGribDumpPanel(QWidget *parent) :
    QWidget(parent),
    currentMsg_(-1),
    data_(0),
    //debugDumpLoaded_(false),
    messageCanBeDecoded_(true)
{
    gribNameSpace_ << "Default" << "geography" << "ls" << "mars"
            << "parameter" << "statistics" << "time" << "vertical";

    QWidget* w;

    QVBoxLayout *dumpLayout = new QVBoxLayout(this);
    dumpLayout->setContentsMargins(0,0,0,0);

    //---------------------------------
    // Tab widget for dump modes
    //---------------------------------

    dumpTab_= new QTabWidget(this);
    dumpLayout->addWidget(dumpTab_);

    //---------------------------------
    // Metview dump
    //--------------------------------

    //Layout
    w = new QWidget(this);
    QVBoxLayout *mvDumpLayout=new QVBoxLayout(w);
    mvDumpLayout->setContentsMargins(0,2,0,0);
    mvDumpLayout->setSpacing(0);
    dumpTab_->addTab(w,tr("Namespaces"));
    dumpTab_->tabBar()->setTabData(dumpTab_->count()-1,"namespace");

    w = new QWidget(this);
    w->setProperty("panelStyle","2");
    QHBoxLayout *nsComboLayout=new  QHBoxLayout(w);
    nsComboLayout->setContentsMargins(2,2,0,2);

    QLabel *nsLabel = new QLabel(tr(" ecCodes namespace:"),w);
    nsLabel->setProperty("panelStyle","2");
    nsCombo_ = new QComboBox(this);
    nsLabel->setBuddy(nsCombo_);

    nsComboLayout->addWidget(nsLabel);
    nsComboLayout->addWidget(nsCombo_);
    nsComboLayout->addStretch(1);

    nsCombo_->addItems(gribNameSpace_);
    nsCombo_->setCurrentIndex(-1);
    mvDumpLayout->addWidget(w);

    //Message tree
    mvDumpModel_= new MvQGribMvDumpModel(this);
    mvDumpSortModel_= new QSortFilterProxyModel(this);
    mvDumpSortModel_->setSourceModel(mvDumpModel_);
    mvDumpSortModel_->setDynamicSortFilter(true);
    mvDumpSortModel_->setFilterRole(Qt::UserRole);
    mvDumpSortModel_->setFilterFixedString("1");
    mvDumpSortModel_->setFilterKeyColumn(0);

    mvDumpTree_= new MvQTreeView(this);
    mvDumpTree_->setObjectName("mvDumpTree");
    mvDumpTree_->setProperty("mvStyle",1);
    mvDumpTree_->setSortingEnabled(true);
    mvDumpTree_->sortByColumn (0,Qt::AscendingOrder);
    //mvDumpTree_->setAlternatingRowColors(true);
    mvDumpTree_->setAllColumnsShowFocus(true);
    mvDumpTree_->setModel(mvDumpSortModel_);
    mvDumpTree_->setRootIsDecorated(false);

    mvDumpTree_->setDragDropMode(QAbstractItemView::DragOnly);

    mvDumpLayout->addWidget(mvDumpTree_);

    //---------------------------------
    // Std dump
    //--------------------------------

    w = new QWidget(this);
    QVBoxLayout *stdDumpLayout=new QVBoxLayout(w);
    stdDumpLayout->setContentsMargins(0,2,0,0);
    stdDumpLayout->setSpacing(0);
    dumpTab_->addTab(w,tr("Standard dump"));
    dumpTab_->tabBar()->setTabData(dumpTab_->count()-1,"std");

    w = new QWidget(this);
    w->setProperty("panelStyle","2");
    QHBoxLayout *stdControlLayout=new  QHBoxLayout(w);
    stdControlLayout->setContentsMargins(2,2,0,2);
    stdDumpLayout->addWidget(w);

    QToolButton* stdTreeTb=new QToolButton(this);
    stdTreeTb->setCheckable(true);
    stdTreeTb->setText(tr("Tree"));

    QToolButton* stdTextTb=new QToolButton(this);
    stdTextTb->setCheckable(true);
    stdTextTb->setText(tr("Text"));

    stdGroup_=new QButtonGroup(this);
    stdGroup_->addButton(stdTreeTb,0);
    stdGroup_->addButton(stdTextTb,1);

    stdControlLayout->addWidget(stdTreeTb);
    stdControlLayout->addWidget(stdTextTb);
    stdControlLayout->addStretch(1);

    //Stacked
    stdDumpStacked_ = new QStackedWidget(this);
    stdDumpLayout->addWidget(stdDumpStacked_);

    stdDumpTree_= new MvQTreeView(this);
    stdDumpModel_= new MvQGribStdDumpModel(this);
    stdDumpTree_->setModel(stdDumpModel_);
    stdDumpTree_->setObjectName("stdDumpTree");
    stdDumpTree_->setProperty("mvStyle",1);
    stdDumpTree_->setAlternatingRowColors(true);
    stdDumpTree_->setAllColumnsShowFocus(true);
    stdDumpTree_->setDragDropMode(QAbstractItemView::DragOnly);    
    stdDumpStacked_->addWidget(stdDumpTree_);

    stdDumpBrowser_=new PlainTextWidget(this);
    stdDumpBrowser_->setProperty("mvStyle","fileContents");
    stdDumpStacked_->addWidget(stdDumpBrowser_);

    connect(stdGroup_,SIGNAL(buttonClicked(int)),
            stdDumpStacked_,SLOT(setCurrentIndex(int)));

    stdExpand_=new MvQTreeExpandState(stdDumpTree_);

    //---------------------------------
    // Wmo dump
    //--------------------------------

    w = new QWidget(this);
    QVBoxLayout *wmoDumpLayout=new QVBoxLayout(w);
    wmoDumpLayout->setContentsMargins(0,2,0,0);
    wmoDumpLayout->setSpacing(0);
    dumpTab_->addTab(w,tr("Sections"));
    dumpTab_->tabBar()->setTabData(dumpTab_->count()-1,"wmo");

    w = new QWidget(this);
    w->setProperty("panelStyle","2");
    QHBoxLayout *wmoControlLayout=new  QHBoxLayout(w);
    wmoControlLayout->setContentsMargins(2,2,0,2);
    wmoDumpLayout->addWidget(w);

    QToolButton* wmoTreeTb=new QToolButton(this);
    wmoTreeTb->setCheckable(true);
    wmoTreeTb->setText(tr("Tree"));

    QToolButton* wmoTextTb=new QToolButton(this);
    wmoTextTb->setCheckable(true);
    wmoTextTb->setText(tr("Text"));

    wmoGroup_=new QButtonGroup(this);
    wmoGroup_->addButton(wmoTreeTb,0);
    wmoGroup_->addButton(wmoTextTb,1);

    wmoControlLayout->addWidget(wmoTreeTb);
    wmoControlLayout->addWidget(wmoTextTb);
    wmoControlLayout->addStretch(1);

    //Stacked
    wmoDumpStacked_ = new QStackedWidget(this);
    wmoDumpLayout->addWidget(wmoDumpStacked_);

    wmoDumpTree_= new MvQTreeView(this);
    wmoDumpModel_= new MvQGribWmoDumpModel(this);
    wmoDumpTree_->setModel(wmoDumpModel_);
    wmoDumpTree_->setObjectName("wmoDumpTree");
    wmoDumpTree_->setProperty("mvStyle",1);
    //wmoDumpTree_->setAlternatingRowColors(true);
    wmoDumpTree_->setAllColumnsShowFocus(true);
    wmoDumpTree_->setDragDropMode(QAbstractItemView::DragOnly);
    wmoDumpTree_->setColumnToDrag(1);;
    wmoDumpStacked_->addWidget(wmoDumpTree_);

    wmoDumpBrowser_=new PlainTextWidget(this);
    wmoDumpBrowser_->setProperty("mvStyle","fileContents");
    wmoDumpStacked_->addWidget(wmoDumpBrowser_);

    connect(wmoGroup_,SIGNAL(buttonClicked(int)),
            wmoDumpStacked_,SLOT(setCurrentIndex(int)));

    wmoExpand_=new MvQTreeExpandState(wmoDumpTree_);

    //---------------------------------
    // Value dump
    //--------------------------------

    w=new QWidget(this);
    QVBoxLayout *valueDumpLayout=new QVBoxLayout(w);
    valueDumpLayout->setContentsMargins(0,2,0,0);
    valueDumpLayout->setSpacing(0);
    dumpTab_->addTab(w,tr("Values"));
    dumpTab_->tabBar()->setTabData(dumpTab_->count()-1,"value");

    w = new QWidget(this);
    w->setProperty("panelStyle","2");
    QHBoxLayout *valueControlLayout=new  QHBoxLayout(w);
    valueControlLayout->setContentsMargins(2,2,0,2);
    valueDumpLayout->addWidget(w);

    //Spin box for index selection
    QLabel *spinLabel = new QLabel(tr(" Go to row:"),w);
    spinLabel->setProperty("panelStyle","2");
    valueRowSpin_ = new QSpinBox(this);
    spinLabel->setBuddy(valueRowSpin_);
    //QHBoxLayout* valueSpinLayout = new QHBoxLayout;
    valueControlLayout->addWidget(spinLabel);
    valueControlLayout->addWidget(valueRowSpin_);

    valueDumpLabel_= new QLabel(w);
    valueDumpLabel_->setProperty("panelStyle","2");
    valueControlLayout->addWidget(valueDumpLabel_);
    valueControlLayout->addStretch(1);

    //valueDumpLayout->addLayout(valueSpinLayout);

    // Signals and slots
    connect(valueRowSpin_, SIGNAL(valueChanged(int)),
        this, SLOT(slotValueRowSpinChanged(int)));

    valueDumpModel_= new MvQGribValueDumpModel(this);
    valueDumpSortModel_= new QSortFilterProxyModel;
    valueDumpSortModel_->setSourceModel(valueDumpModel_);
    valueDumpSortModel_->setDynamicSortFilter(true);
    valueDumpSortModel_->setSortRole(Qt::UserRole);

    valueDumpTree_= new MvQTreeView;
    valueDumpTree_->setObjectName("valueDumpTree");
    valueDumpTree_->setProperty("mvStyle",1);
    valueDumpTree_->setSortingEnabled(true);
    valueDumpTree_->sortByColumn (0,Qt::AscendingOrder);
    //valueDumpTree_->setAlternatingRowColors(true);
    valueDumpTree_->setAllColumnsShowFocus(true);
    valueDumpTree_->setModel(valueDumpSortModel_);
    valueDumpTree_->setRootIsDecorated(false);
    valueDumpTree_->setUniformRowHeights(true);
    valueDumpTree_->setActvatedByKeyNavigation(true);

    valueDumpLayout->addWidget(valueDumpTree_);

    connect(valueDumpTree_,SIGNAL(clicked(QModelIndex)),
        this,SLOT(slotSelectValueRow(QModelIndex)));

    connect(valueDumpTree_,SIGNAL(activated(const QModelIndex&)),
        this,SLOT(slotSelectValueRow(const QModelIndex&)));

    //dumpStacked_->addWidget(w);


    //----------------------------------------
    // Init
    //----------------------------------------

    QFont f;
    QFontMetrics fm(f);

    connect(dumpTab_, SIGNAL(currentChanged(int)),
            this, SLOT(slotCurrentDumpChanged(int)));

    dumpTab_->setCurrentIndex(0); //Default is namespace dump


    //Init ns combo
    nsCombo_->setCurrentIndex(0);

    connect(nsCombo_, SIGNAL(currentIndexChanged(const QString&)),
                this, SLOT(slotSetGribNameSpace(const QString &)));

    connect(nsCombo_, SIGNAL(currentIndexChanged(const QString&)),
                this, SLOT(slotSetGribNameSpace(const QString &)));

    nsCombo_->setCurrentIndex(2); //Default is namesapce "ls"

    //Adjust ns tree columns
    mvDumpTree_->setColumnWidth(0,fm.width("geography.latitudeOfFirstGridPoint"));
    mvDumpTree_->setColumnWidth(1,fm.width("Key type   "));

    stdGroup_->button(0)->setChecked(true);

    //Adjust std tree columns
    stdDumpTree_->setColumnWidth(0,fm.width("latitudeOfFirstGridPointIndegrees"));
    stdDumpTree_->setColumnWidth(1,fm.width("-180.0000000"));

    wmoGroup_->button(0)->setChecked(true);

    //Adjust wmo tree columns
    wmoDumpTree_->setColumnWidth(0,fm.width("Section 5  23-23 "));
    wmoDumpTree_->setColumnWidth(1,fm.width("latitudeOfFirstGridPointIndegrees"));

    //Adjust value tree columns
    valueDumpTree_->setColumnWidth(0,fm.width("10000000 "));
    valueDumpTree_->setColumnWidth(1,fm.width("Latitude  "));
    valueDumpTree_->setColumnWidth(1,fm.width("Longitude  "));
}

MvQGribDumpPanel::~MvQGribDumpPanel()
{
    delete stdExpand_;
    delete wmoExpand_;
}

void MvQGribDumpPanel::init(GribMetaData *data)
{
    data_=data;
}

void MvQGribDumpPanel::loadDumps(int msgCnt)
{
    Q_ASSERT(data_);

    StatusMsgHandler::instance()->show("Message: " + QString::number(msgCnt+1),true);

    //StatusMsgHandler::instance()->show("Load message: " + QString::number(msgCnt+1));

    currentMsg_=msgCnt;
    
    //At this point the first message scan has finished so we know the real  message
	//number. It is not known at the beginning because for multi message fields
	//grib_count_in_file that we use to estimate the message number does not 
	//count the sub messages. So we need to updeate the file info label now.
    
    if(fileInfoLabelNeedsUpdating_)
	{
	  	//updateFileInfoLabel();
		fileInfoLabelNeedsUpdating_=false;
	}	

    //Save expand states in the trees
    if(wmoDumpModel_->hasData())
        wmoExpand_->save();

    if(stdDumpModel_->hasData())
        stdExpand_->save();

    clearDumps();

    if(currentMsg_ <0 || data_->totalMessageNum() ==0)
    {
        messageCanBeDecoded_=false;
        return;
    }

    Q_ASSERT(currentMsg_ >= 0);

    messageCanBeDecoded_=true;

    mvDumpLoaded_=false;
	wmoDumpLoaded_=false;
	stdDumpLoaded_=false;
	valueDumpLoaded_=false;

	//Generate and read grib dumps
    switch(dumpTab_->currentIndex())
	{
	case 0:
		loadMvDump();
		break;
	case 1:
		loadStdDump();
		break;	
    case 2:
		loadWmoDump();
        break;
    case 3:
        loadValueDump();
        break;
	default:
		break;
	}
}

void MvQGribDumpPanel::clearDumps()
{
    clearMvDump();
    clearWmoDump();
    clearStdDump();
    clearValueDump();
}

void MvQGribDumpPanel::loadMvDump()
{	
    Q_ASSERT(currentMsg_>=0);

    if(mvDumpLoaded_ || !messageCanBeDecoded_)
		return;

    StatusMsgHandler::instance()->task("Loading namespace dump");

    GribMvDump* dump = new GribMvDump();
    if(dump->read(data_->fileName(),data_->unfilteredMessageCnt(currentMsg_)))
    {
        //the model takes ownership of the dump
        mvDumpModel_->setDumpData(dump);
        StatusMsgHandler::instance()->done();
    }
    else
    {
        delete dump;
        mvDumpModel_->clear();
        StatusMsgHandler::instance()->failed();
    }

	mvDumpLoaded_=true;
}

void MvQGribDumpPanel::clearMvDump()
{
    mvDumpModel_->clear();
    mvDumpLoaded_=false;
}

void MvQGribDumpPanel::loadWmoDump()
{	
    Q_ASSERT(currentMsg_>=0);

    if(wmoDumpLoaded_ || !messageCanBeDecoded_)
        return;

    StatusMsgHandler::instance()->task("Loading wmo dump");

    GribWmoDump* dump = new GribWmoDump();
    if(dump->read(data_->fileName(),data_->unfilteredMessageCnt(currentMsg_)))
    {
        wmoDumpModel_->setDumpData(dump);
        wmoDumpBrowser_->editor()->setPlainText(QString(dump->text().c_str()));
        StatusMsgHandler::instance()->done();
        wmoExpand_->restore();
    }
    else
    {
        delete dump;
        wmoDumpModel_->clear();
        StatusMsgHandler::instance()->failed();
    }

	wmoDumpLoaded_=true;
}

void MvQGribDumpPanel::clearWmoDump()
{
    if(!wmoDumpLoaded_)
        return;

    wmoDumpModel_->clear();
    wmoDumpBrowser_->clear();
    wmoDumpLoaded_=false;
}


void MvQGribDumpPanel::loadStdDump()
{		
    Q_ASSERT(currentMsg_>=0);

    if(stdDumpLoaded_ || !messageCanBeDecoded_)
        return;

    StatusMsgHandler::instance()->task("Loading default dump");

    GribStdDump* dump = new GribStdDump();
    if(dump->read(data_->fileName(),data_->unfilteredMessageCnt(currentMsg_)))
    {
        stdDumpModel_->setDumpData(dump);
        stdDumpBrowser_->editor()->setPlainText(QString(dump->text().c_str()));
        StatusMsgHandler::instance()->done();
        stdExpand_->restore();
    }
    else
    {
        delete dump;
        stdDumpModel_->clear();
        StatusMsgHandler::instance()->failed();
    }

	stdDumpLoaded_=true;
}

void MvQGribDumpPanel::clearStdDump()
{
    if(!stdDumpLoaded_)
        return;

    stdDumpModel_->clear();
    stdDumpBrowser_->clear();
    stdDumpLoaded_=false;
}


void MvQGribDumpPanel::loadValueDump()
{		
    Q_ASSERT(currentMsg_>=0);

    if(valueDumpLoaded_ || !messageCanBeDecoded_)
        return;

    StatusMsgHandler::instance()->task("Loading value dump");

	//Generate and read grib dump
    int num=0;
    GribValueDump* dump = new GribValueDump();
    if(dump->read(data_->fileName(),data_->unfilteredMessageCnt(currentMsg_)))
    {
        valueDumpModel_->setDumpData(dump);
        num=dump->num();
        StatusMsgHandler::instance()->done();
    }
    else
    {
        delete dump;
        valueDumpModel_->clear();
        StatusMsgHandler::instance()->failed();
    }
	
	// Set min/max values for spinbox
    if(num > 0)
        valueRowSpin_->setRange(1,num);
    else
        valueRowSpin_->setRange(0,0);

    //Update info
    QString info=" (Number of points: " + QString::number(num) + ")";
	//info+="  <b>Average:</b> " + QString::number(dump->average());
	//info+="  <b>Stdev:</b> " + QString::number(dump->stdev());
	//info+=" <b>Skewness:</b> " + QString::number(dump->skewness()); 
	//info+=" <b>Kurtosis:</b> " + QString::number(dump->kurtosis());
	
	valueDumpLabel_->setText(info);

	valueDumpLoaded_=true;
}

void MvQGribDumpPanel::clearValueDump()
{
    if(!valueDumpLoaded_)
        return;

    valueDumpModel_->clear();
    valueDumpLabel_->clear();
    valueDumpLoaded_=false;
}

void MvQGribDumpPanel::slotCurrentDumpChanged(int index)
{
    if(!data_)
        return;

    //Generate and read grib dumps
	switch(index)
	{
	case 0:
		loadMvDump();
		break;
	case 1:
		loadStdDump();
		break;
    case 2:
        loadWmoDump();
        break;
    case 3:
		loadValueDump();
		break;		
	default:
		break;
	}
}

void MvQGribDumpPanel::slotSetGribNameSpace(const QString &ns)
{
    if(mvDumpModel_)
        mvDumpModel_->setGribNameSpace(ns);
}

void MvQGribDumpPanel::slotValueRowSpinChanged(int rowNumber)
{
	if(ignoreValueRowSpinChangeSignal_)
		return;
	
	QModelIndex srcIndex = valueDumpModel_->index(rowNumber-1,0);
	valueDumpTree_->setCurrentIndex(valueDumpSortModel_->mapFromSource(srcIndex));
}

void MvQGribDumpPanel::slotSelectValueRow(const QModelIndex &index)
{
	QModelIndex srcIndex=valueDumpSortModel_->mapToSource(index);
	
  	int cnt=valueDumpModel_->data(valueDumpModel_->index(srcIndex.row(),0)).toInt();
	if(cnt > 0)
	{
		ignoreValueRowSpinChangeSignal_=true;
		valueRowSpin_->setValue(cnt);
		ignoreValueRowSpinChangeSignal_=false;
	}
}  

#if 0
void GribExaminer::slotMessageSpinChanged(int value)
{
    //Override cursor
    QApplication::setOverrideCursor(QCursor(Qt::BusyCursor));

#if 0
    slotSelectMessage(value-1);
#endif

    QApplication::restoreOverrideCursor();

}
#endif

void MvQGribDumpPanel::writeSettings(QSettings& settings)
{
    settings.beginGroup("dump");
    MvQ::saveTabId(settings,"dumpMode",dumpTab_);

    settings.setValue("gribNameSpace",nsCombo_->currentText());
    MvQ::saveTreeColumnWidth(settings,"mvTreeColumnWidth",mvDumpTree_);

    settings.setValue("stdMode",stdGroup_->checkedId());
    MvQ::saveTreeColumnWidth(settings,"stdTreeColumnWidth",stdDumpTree_);

    settings.setValue("wmoMode",wmoGroup_->checkedId());
    MvQ::saveTreeColumnWidth(settings,"wmoTreeColumnWidth",wmoDumpTree_);

    MvQ::saveTreeColumnWidth(settings,"valueTreeColumnWidth",valueDumpTree_);

    settings.endGroup();
}

void MvQGribDumpPanel::readSettings(QSettings& settings)
{
    settings.beginGroup("dump");

    MvQ::initTabId(settings,"dumpMode",dumpTab_);

    MvQ::initComboBox(settings,"gribNameSpace",nsCombo_);
    MvQ::initTreeColumnWidth(settings,"mvTreeColumnWidth",mvDumpTree_);

    MvQ::initButtonGroup(settings,"stdMode",stdGroup_);
    MvQ::initTreeColumnWidth(settings,"stdTreeColumnWidth",stdDumpTree_);

    MvQ::initButtonGroup(settings,"wmoMode",wmoGroup_);
    MvQ::initTreeColumnWidth(settings,"wmoTreeColumnWidth",wmoDumpTree_);

    MvQ::initTreeColumnWidth(settings,"valueTreeColumnWidth",valueDumpTree_);

    settings.endGroup();
}

//==========================================================
//
// GribExaminer
//
//==========================================================

GribExaminer::GribExaminer(string &tmpfilename, QWidget *parent) :
#ifdef ECCODES_UI
    MvQAbstractMessageExaminer("codes_ui",MvQAbstractMessageExaminer::GribType,parent)
#else
    MvQAbstractMessageExaminer("GribExaminer",MvQAbstractMessageExaminer::GribType,parent)
#endif
{	
	setAttribute(Qt::WA_DeleteOnClose);

#ifdef ECCODES_UI
    winTitleBase_="codes_ui";
    settingsName_="codesui-grib";
#else
    winTitleBase_="Grib Examiner (Metview)";
    settingsName_="mv-GribExaminer";
#endif
    setWindowTitle(winTitleBase_);

	//Initial size
	setInitialSize(1100,800);

	//Init
	messageType_="GRIB";

    //gribNameSpace_ << "Default" << "geography" << "ls" << "mars"
    //		<< "parameter" << "statistics" << "time" << "vertical";

	
	fileInfoLabelNeedsUpdating_=true;
    //ignoreValueRowSpinChangeSignal_=false;

    mainPanel_=new MvQGribMainPanel(this);
    centralSplitter_->addWidget(mainPanel_);

    connect(mainPanel_,SIGNAL(keyProfileChanged()),
            this,SLOT(slotKeyProfileChanged()));

    connect(mainPanel_,SIGNAL(newMessageSelected()),
            logPanel_,SLOT(newMessageLoaded()));

    //tmpfilename_ = tmpfilename;

    //Set up panel
    //setupGotoPanel();
    //setupDumpPanel();

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

	setupMenus(menuItems_);

	//-------------------------
	// Settings
	//-------------------------
	
	readSettings();
}
 
GribExaminer::~GribExaminer()
{	
     saveKeyProfiles(true);
     writeSettings();
}

void GribExaminer::initMain(MvMessageMetaData* data)
{
    Q_ASSERT(mainPanel_);
    GribMetaData *grib=static_cast<GribMetaData*>(data);
    mainPanel_->init(grib);
}

void GribExaminer::initDumps()
{
}

void GribExaminer::initAllKeys()
{
	//Get all keys
	MvKeyProfile *prof=new MvKeyProfile("Metview keys");
	prof->addKey(new MvKey("MV_Index","Index","Message index"));
	allKeys_ << prof;

    //GribMetaData *grib=static_cast<GribMetaData*>(data_);

    QStringList gribNameSpace;
    gribNameSpace << "Default" << "geography" << "ls" << "mars"
            << "parameter" << "statistics" << "time" << "vertical";

    Q_ASSERT(data_);
    GribMetaData *gd=static_cast<GribMetaData*>(data_);
    Q_ASSERT(gd);

    foreach(QString ns,gribNameSpace)
	{
		QString pname="Namespace: " + ns;
		MvKeyProfile *prof=new MvKeyProfile(pname.toStdString());
        gd->getKeyList(1,ns.toStdString().c_str(),prof);
		allKeys_ << prof;
    }

}

void GribExaminer::slotLoadFile(QString f)
{
    if(data_->fileName() == f.toStdString())
        return;

    data_->setFileName(f.toStdString());
    currentMessageNo_=-1;

    //Reload
    mainPanel_->reloadData();

    updateFileInfoLabel();

    initAllKeys();
}

void GribExaminer::loadKeyProfile(MvKeyProfile *prof)
{
    Q_ASSERT(mainPanel_);
    mainPanel_->loadKeyProfile(prof);
}

MvKeyProfile* GribExaminer::loadedKeyProfile() const
{
    Q_ASSERT(mainPanel_);
    return mainPanel_->keyProfile();
}

void GribExaminer::slotShowAboutBox()
{
#ifdef ECCODES_UI
    MvQAbout about("codes_ui","",MvQAbout::GribApiVersion);
#else
    MvQAbout about("GribExaminer","",MvQAbout::GribApiVersion | MvQAbout::MetviewVersion);
#endif
    about.exec();
}

void GribExaminer::updateFileInfoLabel()
{
	GribMetaData *grib=static_cast<GribMetaData*>(data_);
	
	fileInfoLabel_->setGribTextLabel(QString(data_->fileName().c_str()),data_->totalMessageNum(),
					 data_->isFilterEnabled(),data_->messageNum(),grib->hasMultiMessage());

    updateWinTitle(QString::fromStdString(data_->fileName()));
}

void GribExaminer::writeSettings()
{
    QSettings settings("ECMWF",settingsName_);
	
    settings.clear();

    MvQAbstractMessageExaminer::writeSettings(settings);

    mainPanel_->writeSettings(settings);
}

void GribExaminer::readSettings()
{
    QSettings settings("ECMWF",settingsName_);

    MvQAbstractMessageExaminer::readSettings(settings);

    mainPanel_->readSettings(settings);
}
