#include "aoqplotpagecontroller.h"

#include "../twodimensionalplotpage.h"

#include "../../quality/statisticsderivator.h"

#include "../../util/logger.h"

AOQPlotPageController::AOQPlotPageController() :
	_page(nullptr),
	_statCollection(nullptr)
{ }

void AOQPlotPageController::UpdatePlot()
{
	if(_page != nullptr)
	{
		updatePlotForSettings(
			_page->GetSelectedKinds(),
			_page->GetSelectedPolarizations(),
			_page->GetSelectedPhases());
	}
}

void AOQPlotPageController::updatePlotForSettings(
	const std::set<QualityTablesFormatter::StatisticKind>& kinds,
	const std::set<SelectedPol>& pols,
	const std::set<PhaseType>& phases)
{
	if(HasStatistics())
	{
		_plot.Clear();
		
		int index = 0;
		for(QualityTablesFormatter::StatisticKind k : kinds)
		{
			for(SelectedPol p : pols)
			{
				for(PhaseType ph : phases)
				{
					plotStatistic(k, p, ph, index, getYDesc(kinds));
					++index;
				}
			}
		}
		
		processPlot(_plot);
		
		if(_page != nullptr)
		{
			_page->Redraw();
		}
	}
}

double AOQPlotPageController::getValue(enum PhaseType phase, const std::complex<long double>& val)
{
	switch(phase)
	{
		default:
		case AmplitudePhaseType: return sqrt(val.real()*val.real() + val.imag()*val.imag());
		case PhasePhaseType: return atan2(val.imag(), val.real());
		case RealPhaseType: return val.real();
		case ImaginaryPhaseType: return val.imag();
	}
}

void AOQPlotPageController::plotStatistic(QualityTablesFormatter::StatisticKind kind, SelectedPol pol, PhaseType phase, int lineIndex, const std::string& yDesc)
{
	StatisticsDerivator derivator(*_statCollection);
	size_t polCount = _statCollection->PolarizationCount();
	const std::map<double, DefaultStatistics> &statistics = getStatistics();
	std::ostringstream s;
	int polIndex = -1;
	s << StatisticsDerivator::GetDescription(kind);
	switch(pol)
	{
	case PolI:
		s << ", pol I";
		polIndex = 0;
		break;
	case PolPP:
		s << ", pol PP";
		polIndex = 0;
		break;
	case PolPQ:
		s << ", pol PQ";
		if(polCount == 4)
			polIndex = 1;
		break;
	case PolQP:
		s << ", pol QP";
		if(polCount == 4)
			polIndex = 2;
		break;
	case PolQQ:
		s << ", pol QQ";
		if(polCount == 4)
			polIndex = 3;
		else if(polCount == 2)
			polIndex = 1;
		break;
	}
	if(phase == RealPhaseType)
		s << " (real)";
	else if(phase == ImaginaryPhaseType)
		s << " (imag)";
	if(polIndex >= 0)
	{
		startLine(_plot, s.str(), lineIndex, yDesc);
		for(std::map<double, DefaultStatistics>::const_iterator i=statistics.begin();i!=statistics.end();++i)
		{
			const double x = i->first;
			std::complex<long double> val;
			
			if(pol == PolI) {
				const std::complex<long double>
					valA = derivator.GetComplexStatistic(kind, i->second, 0),
					valB = derivator.GetComplexStatistic(kind, i->second, polCount-1);
				val = valA*0.5l + valB*0.5l;
			}
			else {
				val = derivator.GetComplexStatistic(kind, i->second, polIndex);
			}
			_plot.PushDataPoint(x, getValue(phase, val));
		}
	}
}

std::string AOQPlotPageController::getYDesc(const std::set<QualityTablesFormatter::StatisticKind>& kinds) const
{
	if(kinds.size() != 1)
		return "Value";
	else
	{
		QualityTablesFormatter::StatisticKind kind = *kinds.begin();
		return StatisticsDerivator::GetDescWithUnits(kind);
	}
}

void AOQPlotPageController::SavePdf(const string& filename, QualityTablesFormatter::StatisticKind kind)
{
	std::set<QualityTablesFormatter::StatisticKind> kinds{kind};
	std::set<SelectedPol> pols{PolI};
	std::set<PhaseType> phases{AmplitudePhaseType};

	updatePlotForSettings(kinds, pols, phases);
	
	_plot.SavePdf(filename);
}

void AOQPlotPageController::SetStatistics(const StatisticsCollection* statCollection, const std::vector<class AntennaInfo>& antennas)
{
	processStatistics(statCollection, antennas);
	
	_statCollection = statCollection;
	UpdatePlot();
}
