#include <windows.h>
#include "config.hpp"

#include <shlobj.h>
#include <knownfolders.h>

inline std::wstring getConfigPath() {
	PWSTR path = nullptr;
	if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &path))) {
		std::wstring result(path);
		CoTaskMemFree(path);
		return result + L"\\RAZEHACK\\Config";
	}
	return L"";
}
inline std::wstring getRazeHackPath() {
	PWSTR path = nullptr;
	if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &path))) {
		std::wstring result(path);
		CoTaskMemFree(path);
		return result + L"\\RAZEHACK";
	}
	return L"";
}

inline nlohmann::json aimConfig::to_json() {
	nlohmann::json json;
	json["rcs"] = rcs;
	json["fov"] = fov;
	json["bone"] = bone;
	json["state"] = state;
	json["bones"] = bones;
	json["hotAim"] = hotAim;
	json["hotKey"] = hotKey;
	json["trigger"] = trigger;
	json["boneMap"] = boneMap;
	json["smoothing"] = smoothing;
	json["hotKeyMap"] = hotKeyMap;
	json["fovCircle"] = fovCircle;
	json["boneSelect"] = boneSelect;
	json["hotTrigger"] = hotTrigger;
	json["playerLock"] = playerLock;
	json["checkSpotter"] = checkSpotted;
	json["hotSelectAim"] = hotSelectAim;
	json["isHotTrigger"] = isHotTrigger;
	json["hotSelectTrigger"] = hotSelectTrigger;
	json["triggerReaction"] = trigger_reaction;
	json["aimLock"] = alaimlock;
	json["engPrediction"] = predictionTest;
	return json;
}

inline bool aimConfig::from_json(nlohmann::json json) {
	try {
		rcs = json["rcs"];
		fov = json["fov"];
		bone = json["bone"];
		state = json["state"];
		bones = json["bones"];
		hotAim = json["hotAim"];
		hotKey = json["hotKey"];
		trigger = json["trigger"];
		boneMap = json["boneMap"];
		smoothing = json["smoothing"];
		hotKeyMap = json["hotKeyMap"];
		fovCircle = json["fovCircle"];
		boneSelect = json["boneSelect"];
		hotTrigger = json["hotTrigger"];
		playerLock = json["playerLock"];
		checkSpotted = json["checkSpotter"];
		hotSelectAim = json["hotSelectAim"];
		isHotTrigger = json["isHotTrigger"];
		hotSelectTrigger = json["hotSelectTrigger"];
		trigger_reaction = json["triggerReaction"];
		alaimlock = json["aimLock"];
		predictionTest = json["engPrediction"];
	}
	catch (nlohmann::json::type_error& ignored) {

	}

	return true;
}


nlohmann::json config::to_json() {
	nlohmann::json json;
	json["aimConf"] = aimConf.to_json();
	return json;
}

void config::load(int index) {
	if (index < 0 || index >= CONFIG_NAMES.size() || index >= MAX_CONFIGS) return;

	try {
		configFiles[index] = json::readFromJsonFile(getConfigPath(), CONFIG_NAMES[index]);
		aimConf.from_json(configFiles[index]["aimConf"]);
	}
	catch (const nlohmann::json::type_error& e) {
		std::ostringstream str;

		str << "[Config.cpp] Error: " << e.what();
	}
}


void config::save(int index) {
	if (index < 0 || index >= CONFIG_NAMES.size() || index >= MAX_CONFIGS) return;

	std::wstring filePath = getConfigPath() + L"\\" + CONFIG_NAMES[index];
	//std::wcout << filePath << " Current index: " << index << std::endl; // debug
	std::ofstream outfile(filePath, std::ios_base::out);
	outfile << config::to_json();
	outfile.close();
}

void config::refresh() {

	CONFIG_NAMES.clear();
	configFiles->clear();
	currentConfigIndex = 0;

	if (!std::filesystem::exists(getRazeHackPath()))
		std::filesystem::create_directory(getRazeHackPath());
	
	if (std::filesystem::exists(getConfigPath()) && std::filesystem::is_directory(getConfigPath()))
	{
		for (auto const& entry : std::filesystem::recursive_directory_iterator(getConfigPath()))
		{
			if (std::filesystem::is_regular_file(entry) && entry.path().extension() == ".json" && 0 != json::readFromJsonFile(getConfigPath(), entry.path().filename().wstring())) 
				CONFIG_NAMES.push_back(entry.path().filename().wstring());
		}
	}
	else
		std::filesystem::create_directory(getConfigPath());
}

void config::create(std::wstring name) {
	std::wstring filePath = getConfigPath() + L"\\" + name;
	std::ofstream outfile(filePath);
	outfile.close();

	CONFIG_NAMES.push_back(name);
}

bool config::exists(int index) {
	if (index < 0 || index >= CONFIG_NAMES.size() || index >= MAX_CONFIGS) return false;

	std::wstring filePath = getConfigPath() + L"\\" + CONFIG_NAMES[index];
	return std::ifstream(filePath).good();
}
