#include "core/anime.h"
#include "core/strings.h"
#include "gui/translate/anime.h"

#include <QCoreApplication>

#include <unordered_map>

namespace Translate {

std::string ToString(const Anime::ListStatus status) {
	switch (status) {
		case Anime::ListStatus::Current: return "Currently watching";
		case Anime::ListStatus::Planning: return "Plan to watch";
		case Anime::ListStatus::Completed: return "Completed";
		case Anime::ListStatus::Dropped: return "Dropped";
		case Anime::ListStatus::Paused: return "On hold";
		default:
		case Anime::ListStatus::NotInList: return "Not in list";
	}
}

std::string ToString(const Anime::SeriesFormat format) {
	switch (format) {
		case Anime::SeriesFormat::Tv: return "TV";
		case Anime::SeriesFormat::TvShort: return "TV short";
		case Anime::SeriesFormat::Ova: return "OVA";
		case Anime::SeriesFormat::Movie: return "Movie";
		case Anime::SeriesFormat::Special: return "Special";
		case Anime::SeriesFormat::Ona: return "ONA";
		case Anime::SeriesFormat::Music: return "Music";
		default:
		case Anime::SeriesFormat::Unknown: return "Unknown";
	}
}

std::string ToString(const Anime::SeriesSeason season) {
	switch (season) {
		case Anime::SeriesSeason::Winter: return "Winter";
		case Anime::SeriesSeason::Summer: return "Summer";
		case Anime::SeriesSeason::Fall: return "Fall";
		case Anime::SeriesSeason::Spring: return "Spring";
		default:
		case Anime::SeriesSeason::Unknown: return "Unknown";
	}
}

std::string ToString(const Anime::SeriesStatus status) {
	switch (status) {
		case Anime::SeriesStatus::Releasing: return "Currently airing";
		case Anime::SeriesStatus::Finished: return "Finished airing";
		case Anime::SeriesStatus::NotYetReleased: return "Not yet aired";
		case Anime::SeriesStatus::Cancelled: return "Cancelled";
		case Anime::SeriesStatus::Hiatus: return "On hiatus";
		default:
		case Anime::SeriesStatus::Unknown: return "Unknown";
	}
}

std::string ToString(const Anime::Service service) {
	switch (service) {
		case Anime::Service::AniList: return "AniList";
		case Anime::Service::MyAnimeList: return "MyAnimeList";
		case Anime::Service::Kitsu: return "Kitsu";
		default:
		case Anime::Service::None: return "None";
	}
}

std::string ToString(const Anime::TitleLanguage language) {
	switch (language) {
		case Anime::TitleLanguage::Native: return "Native";
		case Anime::TitleLanguage::English: return "English";
		default:
		case Anime::TitleLanguage::Romaji: return "Romaji";
	}
}

std::string ToString(const Anime::ScoreFormat format) {
	switch (format) {
		case Anime::ScoreFormat::Point3: return "3-point";
		case Anime::ScoreFormat::Point5: return "5-point";
		case Anime::ScoreFormat::Point10: return "10-point";
		case Anime::ScoreFormat::Point10Decimal: return "10-point Decimal";
		default:
		case Anime::ScoreFormat::Point100: return "100-point";
	}
}

Anime::ListStatus ToListStatus(const std::string& str) {
	static const std::unordered_map<std::string, Anime::ListStatus> map = {
	    {"Currently watching", Anime::ListStatus::Current  },
	    {"Plan to watch",      Anime::ListStatus::Planning },
	    {"Completed",          Anime::ListStatus::Completed},
	    {"Dropped",            Anime::ListStatus::Dropped  },
	    {"On hold",            Anime::ListStatus::Paused   }
    };

	if (map.find(str) == map.end())
		return Anime::ListStatus::NotInList;
	return map.at(str);
}

Anime::SeriesStatus ToSeriesStatus(const std::string& str) {
	static const std::unordered_map<std::string, Anime::SeriesStatus> map = {
	    {"Currently airing", Anime::SeriesStatus::Releasing       },
	    {"Finished airing",  Anime::SeriesStatus::Finished        },
	    {"Not yet aired",    Anime::SeriesStatus::NotYetReleased},
	    {"Cancelled",        Anime::SeriesStatus::Cancelled       },
	    {"On hiatus",        Anime::SeriesStatus::Hiatus          }
    };

	if (map.find(str) == map.end())
		return Anime::SeriesStatus::Unknown;
	return map.at(str);
}

Anime::SeriesSeason ToSeriesSeason(const std::string& str) {
	static const std::unordered_map<std::string, Anime::SeriesSeason> map = {
	    {"Winter", Anime::SeriesSeason::Winter},
	    {"Summer", Anime::SeriesSeason::Summer},
	    {"Fall",   Anime::SeriesSeason::Fall  },
	    {"Spring", Anime::SeriesSeason::Spring}
    };

	if (map.find(str) == map.end())
		return Anime::SeriesSeason::Unknown;
	return map.at(str);
}

Anime::SeriesFormat ToSeriesFormat(const std::string& str) {
	static const std::unordered_map<std::string, Anime::SeriesFormat> map = {
	    {"TV",       Anime::SeriesFormat::Tv      },
        {"TV short", Anime::SeriesFormat::TvShort},
	    {"OVA",      Anime::SeriesFormat::Ova     },
        {"Movie",    Anime::SeriesFormat::Movie   },
	    {"Special",  Anime::SeriesFormat::Special },
        {"ONA",      Anime::SeriesFormat::Ona     },
	    {"Music",    Anime::SeriesFormat::Music   }
    };

	if (map.find(str) == map.end())
		return Anime::SeriesFormat::Unknown;
	return map.at(str);
}

Anime::Service ToService(const std::string& str) {
	static const std::unordered_map<std::string, Anime::Service> map = {
	    {"AniList", Anime::Service::AniList},
	    {"MyAnimeList", Anime::Service::MyAnimeList},
	    {"Kitsu", Anime::Service::Kitsu}
    };

	if (map.find(str) == map.end())
		return Anime::Service::None;
	return map.at(str);
}

Anime::TitleLanguage ToLanguage(const std::string& str) {
	static const std::unordered_map<std::string, Anime::TitleLanguage> map = {
	    {"Romaji",  Anime::TitleLanguage::Romaji },
	    {"Native",  Anime::TitleLanguage::Native },
	    {"English", Anime::TitleLanguage::English}
    };

	if (map.find(str) == map.end())
		return Anime::TitleLanguage::Romaji;
	return map.at(str);
}

Anime::ScoreFormat ToScoreFormat(const std::string& str) {
	static const std::unordered_map<std::string, Anime::ScoreFormat> map = {
		{"3-point",          Anime::ScoreFormat::Point3},
		{"5-point",          Anime::ScoreFormat::Point5},
		{"10-point",         Anime::ScoreFormat::Point10        },
		{"10-point Decimal", Anime::ScoreFormat::Point10Decimal},
		{"100-point",        Anime::ScoreFormat::Point100       },
		/* old values, provided for compatibility */
	    {"POINT_3",          Anime::ScoreFormat::Point3         },
	    {"POINT_5",          Anime::ScoreFormat::Point5         },
	    {"POINT_10",         Anime::ScoreFormat::Point10        },
	    {"POINT_10_DECIMAL", Anime::ScoreFormat::Point10Decimal},
	    {"POINT_100",        Anime::ScoreFormat::Point100       }
    };

	if (map.find(str) == map.end())
		return Anime::ScoreFormat::Point100;
	return map.at(str);
}

/* Localized versions of ToString() functions. Meant for display to the user. */

std::string ToLocalString(const Anime::ListStatus status) {
	switch (status) {
		case Anime::ListStatus::Current: return Strings::ToUtf8String(QCoreApplication::tr("Currently watching"));
		case Anime::ListStatus::Planning: return Strings::ToUtf8String(QCoreApplication::tr("Plan to watch"));
		case Anime::ListStatus::Completed: return Strings::ToUtf8String(QCoreApplication::tr("Completed"));
		case Anime::ListStatus::Dropped: return Strings::ToUtf8String(QCoreApplication::tr("Dropped"));
		case Anime::ListStatus::Paused: return Strings::ToUtf8String(QCoreApplication::tr("On hold"));
		default:
		case Anime::ListStatus::NotInList: return Strings::ToUtf8String(QCoreApplication::tr("Not in list"));
	}
}

std::string ToLocalString(const Anime::SeriesFormat format) {
	switch (format) {
		case Anime::SeriesFormat::Tv: return Strings::ToUtf8String(QCoreApplication::tr("TV"));
		case Anime::SeriesFormat::TvShort: return Strings::ToUtf8String(QCoreApplication::tr("TV short"));
		case Anime::SeriesFormat::Ova: return Strings::ToUtf8String(QCoreApplication::tr("OVA"));
		case Anime::SeriesFormat::Movie: return Strings::ToUtf8String(QCoreApplication::tr("Movie"));
		case Anime::SeriesFormat::Special: return Strings::ToUtf8String(QCoreApplication::tr("Special"));
		case Anime::SeriesFormat::Ona: return Strings::ToUtf8String(QCoreApplication::tr("ONA"));
		case Anime::SeriesFormat::Music: return Strings::ToUtf8String(QCoreApplication::tr("Music"));
		default:
		case Anime::SeriesFormat::Unknown: return Strings::ToUtf8String(QCoreApplication::tr("Unknown"));
	}
}

std::string ToLocalString(const Anime::SeriesSeason season) {
	switch (season) {
		case Anime::SeriesSeason::Winter: return Strings::ToUtf8String(QCoreApplication::tr("Winter"));
		case Anime::SeriesSeason::Summer: return Strings::ToUtf8String(QCoreApplication::tr("Summer"));
		case Anime::SeriesSeason::Fall: return Strings::ToUtf8String(QCoreApplication::tr("Fall"));
		case Anime::SeriesSeason::Spring: return Strings::ToUtf8String(QCoreApplication::tr("Spring"));
		default:
		case Anime::SeriesSeason::Unknown: return Strings::ToUtf8String(QCoreApplication::tr("Unknown"));
	}
}

std::string ToLocalString(const Anime::SeriesStatus status) {
	switch (status) {
		case Anime::SeriesStatus::Releasing: return Strings::ToUtf8String(QCoreApplication::tr("Currently airing"));
		case Anime::SeriesStatus::Finished: return Strings::ToUtf8String(QCoreApplication::tr("Finished airing"));
		case Anime::SeriesStatus::NotYetReleased: return Strings::ToUtf8String(QCoreApplication::tr("Not yet aired"));
		case Anime::SeriesStatus::Cancelled: return Strings::ToUtf8String(QCoreApplication::tr("Cancelled"));
		case Anime::SeriesStatus::Hiatus: return Strings::ToUtf8String(QCoreApplication::tr("On hiatus"));
		default:
		case Anime::SeriesStatus::Unknown: return Strings::ToUtf8String(QCoreApplication::tr("Unknown"));
	}
}

std::string ToLocalString(const Anime::Service service) {
	switch (service) {
		case Anime::Service::AniList: return Strings::ToUtf8String(QCoreApplication::tr("AniList"));
		case Anime::Service::MyAnimeList: return Strings::ToUtf8String(QCoreApplication::tr("MyAnimeList"));
		case Anime::Service::Kitsu: return Strings::ToUtf8String(QCoreApplication::tr("Kitsu"));
		default:
		case Anime::Service::None: return Strings::ToUtf8String(QCoreApplication::tr("None"));
	}
}

std::string ToLocalString(const Anime::TitleLanguage language) {
	switch (language) {
		case Anime::TitleLanguage::Native: return Strings::ToUtf8String(QCoreApplication::tr("Native"));
		case Anime::TitleLanguage::English: return Strings::ToUtf8String(QCoreApplication::tr("English"));
		default:
		case Anime::TitleLanguage::Romaji: return Strings::ToUtf8String(QCoreApplication::tr("Romaji"));
	}
}

std::string ToLocalString(const Anime::ScoreFormat format) {
	switch (format) {
		case Anime::ScoreFormat::Point3: return Strings::ToUtf8String(QCoreApplication::tr("3-point"));
		case Anime::ScoreFormat::Point5: return Strings::ToUtf8String(QCoreApplication::tr("5-point"));
		case Anime::ScoreFormat::Point10: return Strings::ToUtf8String(QCoreApplication::tr("10-point"));
		case Anime::ScoreFormat::Point10Decimal:
			return Strings::ToUtf8String(QCoreApplication::tr("10-point Decimal"));
		default:
		case Anime::ScoreFormat::Point100: return Strings::ToUtf8String(QCoreApplication::tr("100-point"));
	}
}

} // namespace Translate
