/***************************** LICENSE START ***********************************

 Copyright 2016 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 *************************************/

#ifndef BUFREXAMINER_H
#define BUFREXAMINER_H

#include "MvQAbstractMessageExaminer.h"
#include "MvObsSet.h"
#include "BufrFilterEngine.h"

#include <QSettings>

class QComboBox;
class QLabel;
class QPlainTextEdit;
class QSpinBox;
class QSplitter;
class QTabWidget;
class QToolButton;
class QTreeView;
class QVBoxLayout;

class MvQArrowSpinWidget;
class MvQBufrDataModel;
class MvQTreeView;

class PlainTextWidget;

class MessageLabel;
class MvEccBufrMessage;

class BufrCompDataWidget;
class BufrFilterDef;
class BufrDataFilterDialog;
class BufrFilterDialog;
class BufrMetaData;
class MvQBufrMainPanel;
class BufrKeyWidget;
class LocationWidget;
class TreeViewSearchLine;

class MvQBufrDumpPanel : public QWidget, public MvMessageMetaDataObserver
{
    Q_OBJECT
public:
    MvQBufrDumpPanel(QWidget* parent = 0);

    void init(BufrMetaData* data);
    void loadEmpty();
    void loadDumps(int msgCnt, int subsetCnt);
    void loadDumpsForSubset(int subsetCnt);
    void dataFileChanged();
    void setNavigateUncompressed(bool b);
    void loadFilterResult(MvKeyProfile* prof);
    void clear();
    void setHasFilterResult(bool);
    void selectFilterResultTab();
    int currentMessage() const { return currentMsg_; }

    QList<QAction*> actionsToControl() const;

    void readSettings(QSettings& settings);
    void writeSettings(QSettings& settings);

protected slots:
    void slotDataDumpSearch();
    void currentDumpChanged(int);
    void dataDumpSelected(const QModelIndex&);
    void dataDumpDoubleClicked(const QModelIndex&);
    void setEnableDebug(bool b);
    void slotCopyDumpKey();

signals:
    void messageDataInvalid(int);
    void messageSelectedInMap(int);
    void locationScanProgess(int);

protected:
    void locationScanStepChanged(int);

private:
    enum LocationTabContent
    {
        LocationContent,
        FilterResultContent
    };
    enum DumpTabIndex
    {
        DataTabIndex     = 0,
        CompTabIndex     = 1,
        TableTabIndex    = 2,
        DebugTabIndex    = 3,
        LocationTabIndex = 4
    };

    void clearDumps();
    void clearDebugDump();
    void clearLocations();
    void loadDataDump();
    void loadTableDump();
    void loadDebugDump();
    void loadCompDump();
    void loadLocations();
    void updateKeyInfo(const QModelIndex&);
    bool doNavigateUncompressed() const;
    bool isDebugEnabled() const;
    void setLocationContent(LocationTabContent locCont);

    int currentMsg_;     //starts at 0
    int currentSubset_;  //starts at 1
    BufrMetaData* data_;
    QTabWidget* dumpTab_;

    QSplitter* dataDumpSplitter_;
    QTreeView* dataDumpTree_;
    MvQBufrDataModel* dataDumpModel_;
    MessageLabel* dataDumpMessageLabel_;
    QToolButton* dataDumpSearchTb_;
    QToolButton* dataKeyInfoTb_;
    TreeViewSearchLine* dataDumpSearch_;

    QPlainTextEdit* tableTe_;
    PlainTextWidget* debugTe_;

    BufrCompDataWidget* compDumpWidget_;
    MvQKeyProfileTree* compDumpTree_;
    MvQKeyProfileModel* compDumpModel_;
    MvQKeyProfileSortFilterModel* compDumpSortModel_;
    BufrKeyWidget* keyWidget_;

    MessageLabel* locationMessageLabel_;
    LocationWidget* locationW_;
    LocationTabContent locationContent_;

    QAction* actionDebug_;
    QAction* actionNavigateUncompressed_;

    bool messageCanBeDecoded_;
    bool debugDumpLoaded_;
    bool navigateUncompressed_;
    bool compDumpLoaded_;
    bool locationLoaded_;
};

class MvQBufrMainPanel : public QWidget
{
    Q_OBJECT

public:
    MvQBufrMainPanel(bool filtered, QWidget* parent);
    void init(BufrMetaData*);
    void clear();
    MvKeyProfile* keyProfile() const;
    void loadKeyProfile(MvKeyProfile* prof);
    void reloadData(bool hasFilterResult);
    void messageFilterChanged(const BufrFilterDef&);
    void setFilterInfo(bool filtered, int oriNum, int num);
    bool doNavigateUncompressed() const;
    void loadFilterResult(MvKeyProfile*);
    void selectFilterResultTab();
    QString fileName() const;
    BufrMetaData* data() const { return data_; }
    int currentMessage() const { return dumpPanel_->currentMessage(); }

    void readSettings(QSettings& settings);
    void writeSettings(QSettings& settings);

protected slots:
    void messageSelected(int);
    void messageChangedInGoto(int value);
    void subsetChangedInGoto(int value);
    void messageSelectedInMap(int);
    void navigateUncompressedChanged(bool);

signals:
    void newMessageSelected(int);
    void keyProfileChanged();
    void messageNumDetermined();

private:
    BufrMetaData* data_;
    MvQMessagePanel* messagePanel_;
    MvQBufrDumpPanel* dumpPanel_;
    MessageControlPanel* gotoPanel_;
    QSplitter* dataSplitter_;
    bool navigateUncompressed_;
    bool inProfileLoad_;
    QAction* actionDebug_;
    QAction* actionNavigateUncompressed_;
};

class BufrExaminer : public MvQAbstractMessageExaminer, public BufrFilterEngineObserver
{
    Q_OBJECT

public:
    BufrExaminer(QWidget* parent = 0);
    ~BufrExaminer();

    void notifyBufrFilterProgress(int n);

protected slots:
    void slotShowAboutBox();
    void slotStatusMessage(QString);
    void slotLoadFile(QString);
    void slotUncompressedMode(bool);
    void slotFilterEdit();
    void slotFilterRevert();
    void slotRunFilter(const BufrFilterDef&);
    void slotSaveFilteredFile(bool);
    void newMessageLoaded(int msg);
    void updateFileInfoLabel();
    void initFilterEditorHelpers();

signals:
    void filterProgess(int);

protected:
    MvKeyProfile* loadedKeyProfile() const;

private:
    enum MainTabIndex
    {
        OriiginalTabIndex = 0,
        FilteredTabIndex  = 1
    };

    void setupFileMenu();
    void setupFilterMenu();

    void initMain(MvMessageMetaData* data);
    void initDumps();
    void initAllKeys();
    void addCloseButtonFilteredTab();
    void createFilteredPanel();
    void loadKeyProfile(MvKeyProfile*);
    void loadFile(QString);
    void loadEmptyFile(QString f);
    void loadFilteredFile(QString, MvKeyProfile*);
    void loadFilteredEmptyFile(QString f);

    void writeSettings();
    void readSettings();

    QTabWidget* mainTab_;
    MvQBufrMainPanel* mainPanel_;
    MvQBufrMainPanel* filteredPanel_;
    BufrMetaData* filteredData_;
    bool messageCanBeDecoded_;
    QAction* actionFilterEdit_;
    QAction* actionFilterRemove_;
    QAction* actionSave_;
    BufrFilterDialog* filterDialog_;
};

#endif  // BUFREXAMINER_H
