/**
 * config.cpp:
 * parses the config
 *
 * much of this is similar to the code used in
 * wgsdk...
 * maybe some of this will be C++-ified someday ;)
**/
#include <filesystem> /* Sorry, C++17 is just sexy. if you have boost you can probably change this */
#ifdef MACOSX
#include <NSSystemDirectories.h>
#endif
#include <limits.h>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include "json.h"
#include "config.h"
#include "window.h"
#include "filesystem.h"

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

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

int Config::Load() {
	std::filesystem::path cfg_path = get_config_path();
	if (!std::filesystem::exists(cfg_path))
		return 0;
	std::ifstream config_in(cfg_path.string().c_str(), std::ifstream::in);
	auto config_js = nlohmann::json::parse(config_in);
/* this macro will make it easier to edit these in the future, if needed */
#define GET_CONFIG_VALUE(pointer, location, struct, default) \
	struct = (config_js.contains(pointer)) ? (location) : (default)
	GET_CONFIG_VALUE("/General/Service"_json_pointer, (enum AnimeListServices)config_js["General"]["Service"].get<int>(), service, NONE);
	GET_CONFIG_VALUE("/Authorization/AniList/Auth Token"_json_pointer, config_js["Authorization"]["AniList"]["Auth Token"].get<std::string>(), anilist.auth_token, "");
	GET_CONFIG_VALUE("/Authorization/AniList/Username"_json_pointer, config_js["Authorization"]["AniList"]["Username"].get<std::string>(), anilist.username, "");
	GET_CONFIG_VALUE("/Authorization/AniList/User ID"_json_pointer, config_js["Authorization"]["AniList"]["User ID"].get<int>(), anilist.user_id, 0);
	GET_CONFIG_VALUE("/Appearance/Theme"_json_pointer, StringToTheme[config_js["Appearance"]["Theme"].get<std::string>()], theme, OS);
#undef GET_CONFIG_VALUE
	config_in.close();
	return 0;
}

int Config::Save() {
	std::filesystem::path cfg_path = get_config_path();
	if (!std::filesystem::exists(cfg_path.parent_path()))
		std::filesystem::create_directories(cfg_path.parent_path());
	std::ofstream config_out(cfg_path.string().c_str(), std::ofstream::out | std::ofstream::trunc);
	nlohmann::json config_js = {
		{"General", {
			{"Service", service}
		}},
		{"Authorization", {
			{"AniList", {
				{"Auth Token", anilist.auth_token},
				{"Username",   anilist.username},
				{"User ID",    anilist.user_id}
			}}
		}},
		{"Appearance", {
			{"Theme", ThemeToString[theme]}
		}}
	};
	config_out << std::setw(4) << config_js << std::endl;
	config_out.close();
	return 0;
}
