#include "core/anime_season.h"
#include "core/session.h"

namespace Anime {

static bool WinterStartsInDecember()
{
	switch (session.config.service) {
	case Service::MyAnimeList:
		return false;
	default:
		return true;
	}
}

static Season::Name GetSeasonForMonth(Date::Month month)
{
	if (WinterStartsInDecember()) {
		switch (month) {
		case Date::Month::Dec:
		case Date::Month::Jan:
		case Date::Month::Feb:
			return Season::Name::Winter;
		case Date::Month::Mar:
		case Date::Month::Apr:
		case Date::Month::May:
			return Season::Name::Spring;
		case Date::Month::Jun:
		case Date::Month::Jul:
		case Date::Month::Aug:
			return Season::Name::Summer;
		case Date::Month::Sep:
		case Date::Month::Oct:
		case Date::Month::Nov:
			return Season::Name::Autumn;
		default:
			return Season::Name::Unknown;
		}
	} else {
		switch (month) {
		case Date::Month::Jan:
		case Date::Month::Feb:
		case Date::Month::Mar:
			return Season::Name::Winter;
		case Date::Month::Apr:
		case Date::Month::May:
		case Date::Month::Jun:
			return Season::Name::Spring;
		case Date::Month::Jul:
		case Date::Month::Aug:
		case Date::Month::Sep:
			return Season::Name::Summer;
		case Date::Month::Oct:
		case Date::Month::Nov:
		case Date::Month::Dec:
			return Season::Name::Autumn;
		default:
			return Season::Name::Unknown;
		}
	}
}

Season::Season(Season::Name s, Date::Year y)
{
	season = s;
	year = y;
}

Season::Season(const Date &date)
{
	std::optional<Date::Month> month = date.GetMonth();
	if (month)
		season = GetSeasonForMonth(month.value());

	std::optional<Date::Year> y = date.GetYear();
	if (y)
		year = y.value();
}

bool Season::operator==(const Season &o) const
{
	return (season == o.season && year == o.year);
}

bool Season::operator!=(const Season &o) const
{
	return !(*this == o);
}

bool Season::operator<(const Season &o) const
{
	return std::tie(season, year) < std::tie(o.season, o.year);
}

bool Season::operator>(const Season &o) const
{
	return (o < *this);
}

bool Season::operator<=(const Season &o) const
{
	return !(o > *this);
}

bool Season::operator>=(const Season &o) const
{
	return !(*this < o);
}

Season &Season::operator++()
{
	switch (season) {
	case Season::Name::Winter:
		season = Season::Name::Spring;
		break;
	case Season::Name::Spring:
		season = Season::Name::Summer;
		break;
	case Season::Name::Summer:
		season = Season::Name::Autumn;
		break;
	case Season::Name::Autumn:
		season = Season::Name::Winter;
		year++;
		break;
	default:
		season = Season::Name::Unknown;
		break;
	}

	return *this;
}

Season &Season::operator--()
{
	switch (season) {
	case Season::Name::Winter:
		season = Season::Name::Autumn;
		year--;
		break;
	case Season::Name::Spring:
		season = Season::Name::Winter;
		break;
	case Season::Name::Summer:
		season = Season::Name::Spring;
		break;
	case Season::Name::Autumn:
		season = Season::Name::Summer;
		break;
	default:
		season = Season::Name::Unknown;
		break;
	}

	return *this;
}

} // namespace Anime
