#include "gui/pages/statistics.h"
#include "core/anime_db.h"
#include "core/session.h"
#include "core/strings.h"
#include "core/time.h"
#include "gui/pages/anime_list.h"
#include "gui/widgets/graph.h"
#include "gui/widgets/text.h"

#include <QString>
#include <QTextDocument>
#include <QTextStream>
#include <QTimer>
#include <QVBoxLayout>
#include <QWidget>

#include <cmath>
#include <sstream>

StatisticsPage::StatisticsPage(QWidget* parent)
	: QFrame(parent) {
	setBackgroundRole(QPalette::Base);

	QVBoxLayout* layout = new QVBoxLayout(this);

	setFrameShape(QFrame::Box);
	setFrameShadow(QFrame::Sunken);

	setAutoFillBackground(true);

	const std::vector<std::pair<std::string, std::string>> al_data_template = {
		{Strings::Translate("Anime count:"), ""},
		{Strings::Translate("Episode count:"), ""},
		{Strings::Translate("Time spent watching:"), ""},
		{Strings::Translate("Time to complete:"), ""},
		{Strings::Translate("Average score:"), ""},
		{Strings::Translate("Score deviation:"), ""},
	};

	_anime_list.GetHeader().SetText(Strings::Translate("Anime List"));
	_anime_list.GetContent().SetData(al_data_template);

	layout->addWidget(&_anime_list);

	{
		QWidget* score_dist_widget = new QWidget(this);
		QVBoxLayout* score_dist_layout = new QVBoxLayout(score_dist_widget);

		TextWidgets::Header* hdr = new TextWidgets::Header(score_dist_widget);
		hdr->SetText(Strings::Translate("Score distribution"));
		score_dist_layout->addWidget(hdr);

		/* Ew */
		{
			QWidget* score_graph_parent = new QWidget(score_dist_widget);
			QVBoxLayout* score_parent_layout = new QVBoxLayout(score_graph_parent);

			score_parent_layout->addWidget(&_score_distribution_graph);

			score_parent_layout->setSpacing(0);
			score_parent_layout->setContentsMargins(12, 0, 0, 0);

			score_dist_layout->addWidget(score_graph_parent);
		}

		score_dist_layout->setContentsMargins(0, 0, 0, 0);

		layout->addWidget(score_dist_widget);
	}

	const std::vector<std::pair<std::string, std::string>> app_data_template = {
		{Strings::Translate("Uptime:"), ""},
		{Strings::Translate("Requests made:"), ""},
	};

	_application.GetHeader().SetText(Strings::Translate("Minori"));
	_application.GetContent().SetData(app_data_template);

	layout->addWidget(&_application);

	layout->addStretch();

	QTimer* timer = new QTimer(this);
	connect(timer, &QTimer::timeout, this, [this] {
		if (isVisible())
			UpdateStatistics();
	});
	timer->start(1000); // update statistics every second
}

void StatisticsPage::showEvent(QShowEvent*) {
	UpdateStatistics();
}

inline int GetTotalWithScore(const int score) {
	int count = 0;
	for (const auto& item : Anime::db.items)
		if (item.second.IsInUserList() && item.second.GetUserScore() == score)
			count++;
	return count;
}

void StatisticsPage::UpdateStatistics() {
	const std::vector<std::pair<std::string, std::string>> al_data = {
		{Strings::Translate("Anime count:"), Strings::ToUtf8String(Anime::db.GetTotalAnimeAmount())},
		{Strings::Translate("Episode count:"), Strings::ToUtf8String(Anime::db.GetTotalEpisodeAmount())},
		{Strings::Translate("Time spent watching:"), Time::GetSecondsAsAbsoluteString(Time::Units::Minutes, Anime::db.GetTotalWatchedAmount(), 60.0)},
		{Strings::Translate("Time to complete:"), Time::GetSecondsAsAbsoluteString(Time::Units::Minutes, Anime::db.GetTotalPlannedAmount(), 60.0)},
		{Strings::Translate("Average score:"), Strings::ToUtf8String(Anime::db.GetAverageScore())},
		{Strings::Translate("Score deviation:"), Strings::ToUtf8String(Anime::db.GetScoreDeviation())},
	};

	_anime_list.GetContent().SetData(al_data);

	_score_distribution_graph.Clear();
	for (int i = 10; i <= 100; i += 10)
		_score_distribution_graph.AddItem(i, GetTotalWithScore(i));

	/* Application */
	const std::vector<std::pair<std::string, std::string>> app_data_template = {
		{Strings::Translate("Uptime:"), Time::GetSecondsAsAbsoluteString(Time::Units::Seconds, session.uptime() / 1000)},
		{Strings::Translate("Requests made:"), Strings::ToUtf8String(session.GetRequests())},
	};

	_application.GetContent().SetData(app_data_template);
}
