/**
 * config.cpp:
 * parses the config... lol
 **/
#include "core/config.h"
#include "core/anime.h"
#include "core/filesystem.h"
#include "core/json.h"
#include <cstdlib>
#include <cstring>
#include <filesystem>
#include <fstream>
#include <limits.h>

std::map<std::string, Themes> StringToTheme = {
    {"Default", Themes::OS   },
    {"Light",   Themes::LIGHT},
    {"Dark",    Themes::DARK }
};

std::map<Themes, std::string> ThemeToString = {
    {Themes::OS,    "Default"},
    {Themes::LIGHT, "Light"  },
    {Themes::DARK,  "Dark"   }
};

std::map<Anime::Services, std::string> ServiceToString{
    {Anime::Services::NONE,    "None"   },
    {Anime::Services::ANILIST, "AniList"}
};

std::map<std::string, Anime::Services> StringToService{
    {"None",    Anime::Services::NONE   },
    {"AniList", Anime::Services::ANILIST}
};

std::map<Anime::TitleLanguage, std::string> AnimeTitleToStringMap = {
    {Anime::TitleLanguage::ROMAJI,  "Romaji" },
    {Anime::TitleLanguage::NATIVE,  "Native" },
    {Anime::TitleLanguage::ENGLISH, "English"}
};

std::map<std::string, Anime::TitleLanguage> StringToAnimeTitleMap = {
    {"Romaji",  Anime::TitleLanguage::ROMAJI },
    {"Native",  Anime::TitleLanguage::NATIVE },
    {"English", Anime::TitleLanguage::ENGLISH}
};

int Config::Load() {
	std::string cfg_path = Filesystem::GetConfigPath();
	if (!Filesystem::Exists(cfg_path))
		return 0;
	std::ifstream config(cfg_path.c_str(), std::ifstream::in);
	auto config_js = nlohmann::json::parse(config);
	service = StringToService[JSON::GetString(config_js, "/General/Service"_json_pointer)];
	anime_list.language = StringToAnimeTitleMap[JSON::GetString(
	    config_js, "/Anime List/Display only aired episodes"_json_pointer, "Romaji")];
	anime_list.display_aired_episodes =
	    JSON::GetBoolean(config_js, "/Anime List/Display only aired episodes"_json_pointer, true);
	anime_list.display_available_episodes =
	    JSON::GetBoolean(config_js, "/Anime List/Display only available episodes in library"_json_pointer, true);
	anime_list.highlight_anime_if_available =
	    JSON::GetBoolean(config_js, "/Anime List/Highlight anime if available"_json_pointer, true);
	anime_list.highlighted_anime_above_others =
	    JSON::GetBoolean(config_js, "/Anime List/Display highlighted anime above others"_json_pointer);
	anilist.auth_token = JSON::GetString(config_js, "/Authorization/AniList/Auth Token"_json_pointer);
	anilist.username = JSON::GetString(config_js, "/Authorization/AniList/Username"_json_pointer);
	anilist.user_id = JSON::GetInt(config_js, "/Authorization/AniList/User ID"_json_pointer);
	theme = StringToTheme[JSON::GetString(config_js, "/Appearance/Theme"_json_pointer)];
	config.close();
	return 0;
}

int Config::Save() {
	std::string cfg_path = Filesystem::GetConfigPath();
	if (!Filesystem::Exists(Filesystem::GetParentDirectory(cfg_path)))
		Filesystem::CreateDirectories(Filesystem::GetParentDirectory(cfg_path));
	std::ofstream config(cfg_path.c_str(), std::ofstream::out | std::ofstream::trunc);
	// clang-format off
	nlohmann::json config_js = {
		{"General",	{
			{"Service", ServiceToString[service]}
		}},
		{"Anime List", {
			{"Title language", AnimeTitleToStringMap[anime_list.language]},
			{"Display only aired episodes", anime_list.display_aired_episodes},
			{"Display only available episodes in library", anime_list.display_available_episodes},
			{"Highlight anime if available", anime_list.highlight_anime_if_available},
			{"Display highlighted anime above others", anime_list.highlighted_anime_above_others}
		}},
		{"Authorization", {
			{"AniList", {
				{"Auth Token", anilist.auth_token},
				{"Username", anilist.username},
				{"User ID", anilist.user_id}
			}}
		}},
		{"Appearance", {
			{"Theme", ThemeToString[theme]}
		}}
	};
	// clang-format on
	config << std::setw(4) << config_js << std::endl;
	config.close();
	return 0;
}
