#include "aoqplotwindow.h"

#include "controllers/antennapagecontroller.h"
#include "controllers/aoqplotcontroller.h"
#include "controllers/baselinepagecontroller.h"
#include "controllers/blengthpagecontroller.h"
#include "controllers/frequencypagecontroller.h"
#include "controllers/histogrampagecontroller.h"
#include "controllers/tfpagecontroller.h"
#include "controllers/timepagecontroller.h"

#include <limits>

#include <gtkmm/main.h>
#include <gtkmm/messagedialog.h>

#include "../structures/msmetadata.h"

#include "../quality/histogramtablesformatter.h"
#include "../quality/histogramcollection.h"
#include "../quality/statisticscollection.h"

#include "baselineplotpage.h"
#include "blengthplotpage.h"
#include "frequencyplotpage.h"
#include "histogrampage.h"
#include "summarypage.h"
#include "timefrequencyplotpage.h"

AOQPlotWindow::AOQPlotWindow(AOQPlotController* controller) :
	_controller(controller),
	_activeSheetIndex(-1),
	_pageMenuButton("Sheet"),
	_baselineMI(_pageGroup, "Baselines"),
	_antennaeMI(_pageGroup, "Antennae"),
	_bLengthMI(_pageGroup, "Baseline lengths"),
	_timeMI(_pageGroup, "Time"),
	_frequencyMI(_pageGroup, "Frequency"),
	_timeFrequencyMI(_pageGroup, "Time-frequency"),
	_summaryMI(_pageGroup, "Summary"),
	_histogramMI(_pageGroup, "Histograms")
{
	set_default_icon_name("aoqplot");
	
	_toolbar.append(_pageMenuButton);
	_pageMenuButton.set_menu(_pageMenu);
	_pageMenu.append(_baselineMI);
	_baselineMI.signal_toggled().connect(sigc::mem_fun(*this, &AOQPlotWindow::onChangeSheet));
	_pageMenu.append(_antennaeMI);
	_antennaeMI.signal_toggled().connect(sigc::mem_fun(*this, &AOQPlotWindow::onChangeSheet));
	_pageMenu.append(_bLengthMI);
	_bLengthMI.signal_toggled().connect(sigc::mem_fun(*this, &AOQPlotWindow::onChangeSheet));
	_pageMenu.append(_timeMI);
	_timeMI.signal_toggled().connect(sigc::mem_fun(*this, &AOQPlotWindow::onChangeSheet));
	_pageMenu.append(_frequencyMI);
	_frequencyMI.signal_toggled().connect(sigc::mem_fun(*this, &AOQPlotWindow::onChangeSheet));
	_pageMenu.append(_timeFrequencyMI);
	_timeFrequencyMI.signal_toggled().connect(sigc::mem_fun(*this, &AOQPlotWindow::onChangeSheet));
	_pageMenu.append(_summaryMI);
	_summaryMI.signal_toggled().connect(sigc::mem_fun(*this, &AOQPlotWindow::onChangeSheet));
	_pageMenu.append(_histogramMI);
	_histogramMI.signal_toggled().connect(sigc::mem_fun(*this, &AOQPlotWindow::onChangeSheet));
	_pageMenu.show_all_children();
	
	_vBox.pack_start(_toolbar, Gtk::PACK_SHRINK);
	
	_vBox.pack_end(_statusBar, Gtk::PACK_SHRINK);
	_statusBar.push("Quality plot util is ready. Author: André Offringa (offringa@gmail.com)");
	
	add(_vBox);
	
	_openOptionsWindow.SignalOpen().connect(sigc::mem_fun(*this, &AOQPlotWindow::onOpenOptionsSelected));
	signal_hide().connect(sigc::mem_fun(*this, &AOQPlotWindow::onHide));
	
	_controller->Attach(this);
}

void AOQPlotWindow::Open(const std::vector<std::string> &files)
{
	show_all();
	_openOptionsWindow.ShowForFile(files);
}

void AOQPlotWindow::onOpenOptionsSelected(const std::vector<std::string>& files, bool downsampleTime, bool downsampleFreq, size_t timeCount, size_t freqCount, bool correctHistograms)
{
	_controller->ReadStatistics(files, downsampleTime, downsampleFreq, timeCount, freqCount, correctHistograms);
	_activeSheetIndex = -1;
	onChangeSheet();
	show();
}

void AOQPlotWindow::onStatusChange(const std::string &newStatus)
{
	_statusBar.pop();
	_statusBar.push(newStatus);
}

void AOQPlotWindow::onChangeSheet()
{
	int selectedSheet = -1;
	if(_baselineMI.get_active())
		selectedSheet = 0;
	else if(_antennaeMI.get_active())
		selectedSheet = 1;
	else if(_bLengthMI.get_active())
		selectedSheet = 2;
	else if(_timeMI.get_active())
		selectedSheet = 3;
	else if(_frequencyMI.get_active())
		selectedSheet = 4;
	else if(_timeFrequencyMI.get_active())
		selectedSheet = 5;
	else if(_summaryMI.get_active())
		selectedSheet = 6;
	else if(_histogramMI.get_active())
		selectedSheet = 7;
	
	if(selectedSheet != _activeSheetIndex)
	{
		switch(selectedSheet)
		{
		case 0:
			_pageController.reset(new BaselinePageController());
			_activeSheet.reset(new BaselinePlotPage( static_cast<BaselinePageController*>(_pageController.get())));
			SetStatus("Baseline statistics");
			break;
		case 1:
			_pageController.reset(new AntennaePageController());
			_activeSheet.reset(new TwoDimensionalPlotPage( static_cast<AntennaePageController*>(_pageController.get())));
			SetStatus("Antennae statistics");
			break;
		case 2:
			_pageController.reset(new BLengthPageController());
			_activeSheet.reset(new BLengthPlotPage( static_cast<BLengthPageController*>(_pageController.get())));
			SetStatus("Baseline length statistics");
			break;
		case 3:
			_pageController.reset(new TimePageController());
			_activeSheet.reset(new TwoDimensionalPlotPage( static_cast<TimePageController*>(_pageController.get())));
			SetStatus("Time statistics");
			break;
		case 4:
			_pageController.reset(new FrequencyPageController());
			_activeSheet.reset(new FrequencyPlotPage(static_cast<FrequencyPageController*>(_pageController.get())));
			SetStatus("Frequency statistics");
			break;
		case 5:
			_pageController.reset(new TFPageController());
			_activeSheet.reset(new TimeFrequencyPlotPage( static_cast<TFPageController*>(_pageController.get())));
			SetStatus("Time-frequency statistics");
			break;
		case 6:
			_pageController.reset(new SummaryPageController());
			_activeSheet.reset(new SummaryPage( static_cast<SummaryPageController*>(_pageController.get())));
			SetStatus("Summary");
			break;
		case 7:
			_pageController.reset(new HistogramPageController());
			_activeSheet.reset(new HistogramPage( static_cast<HistogramPageController*>(_pageController.get())));
			SetStatus("Histograms");
			break;
		}
		
		_activeSheetIndex = selectedSheet;
		_controller->Initialize(_pageController.get(), selectedSheet != 5);
		_activeSheet->SignalStatusChange().connect(sigc::mem_fun(*this, &AOQPlotWindow::onStatusChange));
		_activeSheet->InitializeToolbar(_toolbar);
		_toolbar.show_all();
		_vBox.pack_start(*_activeSheet);
		_activeSheet->show_all();
	}
}

void AOQPlotWindow::ShowError(const std::string& message)
{
	Gtk::MessageDialog dialog(*this, message, false, Gtk::MESSAGE_ERROR);
	dialog.run();
}
