#include "ApplicationData.h"
#include "ImguiBase.h"
#include "Util.h"
#include "Settings.h"

#include <chrono>

extern bool justDocked;
extern DrawData* gDrawData;
extern ApplicationData* gAppData;

void initSettings(DrawData& drawData, ApplicationData& appData)
{
	ImGuiSettingsHandler ini_handler;
	ini_handler.TypeName = APPLICATION_SETTINGS_GROUP;
	ini_handler.TypeHash = ImHashStr(APPLICATION_SETTINGS_GROUP);
	ini_handler.ReadOpenFn = settingsReadOpen;
	ini_handler.ReadLineFn = settingsReadLine;
	ini_handler.WriteAllFn = settingsWriteAll;
	GImGui->SettingsHandlers.push_back(ini_handler);
	ImGui::LoadIniSettingsFromDisk("imgui.ini");
	applySettings(drawData, appData);
}

void* settingsReadOpen(ImGuiContext* ctx, ImGuiSettingsHandler* handler, const char* name)
{
	ApplicationSettings* settings = &gAppData->settings;
	*settings = ApplicationSettings();
	return (void*)settings;
}

void settingsReadLine(ImGuiContext* ctx, ImGuiSettingsHandler* handler, void* entry, const char* line)
{
	if (strlen(line) == 0) return;

	ApplicationSettings* settings = (ApplicationSettings*)entry;

	int docked;
	if (sscanf_s(line, "docked=%i", &docked))
	{
		settings->docked = (bool)docked;
	}
	
	int autostart;
	if (sscanf_s(line, "autostart=%i", &autostart))
	{
		settings->autostart = (bool)autostart;
	}
	
	std::string taskName{};
	taskName.resize(MAX_TASK_NAME_LENGTH);
	if (sscanf_s(line, "taskname=%s", &taskName[0], MAX_TASK_NAME_LENGTH))
	{
		settings->taskNames.push_back(taskName);
	}
	
	std::string task{};
	task.resize(MAX_TASK_NAME_LENGTH);
	int year;
	unsigned int month;
	unsigned int day;
	if (sscanf_s(line, "task=%d-%u-%u %s", &year, &month, &day, &task[0], MAX_TASK_NAME_LENGTH))
	{
		std::chrono::year_month_day date = std::chrono::year_month_day{ std::chrono::year{year}, std::chrono::month{month}, std::chrono::day{day} };
		if (settings->tasks.contains(task))
		{
			settings->tasks[task].push_back(date);
		}
		else
		{
			settings->tasks.insert({ task, std::vector{ date } });
		}
	}

	std::string baseStationMac{};
	baseStationMac.resize(MAX_MAC_ADDRESS_LENGTH);
	if (sscanf_s(line, "baseStationMac=%s", &baseStationMac[0], MAX_MAC_ADDRESS_LENGTH))
	{
		settings->baseStationMacAdresses.push_back(baseStationMac);
	}

	// baseStationShowConsole
	int baseStationShowConsole;
	if (sscanf_s(line, "baseStationShowConsole=%i", &baseStationShowConsole))
	{
		settings->baseStationShowConsole = (bool)baseStationShowConsole;
	}

	float timerDuration;
	if (sscanf_s(line, "timerDuration=%f", &timerDuration))
	{
		settings->timerDuration = timerDuration;
	}
	
	float timerRepeatDuration;
	if (sscanf_s(line, "timerRepeatDuration=%f", &timerRepeatDuration))
	{
		settings->timerRepeatDuration = timerRepeatDuration;
	}

	int timerRepeating;
	if (sscanf_s(line, "timerRepeating=%i", &timerRepeating))
	{
		settings->timerRepeating = (bool)timerRepeating;
	}
}

void settingsWriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* outBuf)
{
	outBuf->appendf("[%s][%s]\n", APPLICATION_SETTINGS_GROUP, APPLICATION_SETTINGS_GROUP);
	outBuf->appendf("docked=%i\n", (int)gAppData->settings.docked);
	outBuf->appendf("autostart=%i\n", (int)gAppData->settings.autostart);

	for (std::string& taskName : gAppData->settings.taskNames)
	{
		outBuf->appendf("taskname=%s\n", taskName.c_str());
	}

	for (auto& task : gAppData->settings.tasks)
	{
		for (auto& date : task.second)
		{
			outBuf->appendf("task=%d-%u-%u %s\n", int{ date.year() }, unsigned int{ date.month() }, unsigned int{ date.day() }, task.first.c_str());
		}
	}

	for (std::string& baseStationMac : gAppData->settings.baseStationMacAdresses)
	{
		outBuf->appendf("baseStationMac=%s\n", baseStationMac.c_str());
	}

	outBuf->appendf("timerDuration=%f\n", gAppData->settings.timerDuration);
	outBuf->appendf("timerRepeatDuration=%f\n", gAppData->settings.timerRepeatDuration);
	outBuf->appendf("timerRepeating=%i\n", (int)gAppData->settings.timerRepeating);
}

void applySettings(DrawData& drawData, ApplicationData& appData)
{
	updateDocked(drawData, appData);
	setAutostart(appData.settings.autostart);
}

void updateDocked(DrawData& drawData, ApplicationData& appData)
{
	justDocked = true;

	glfwSetWindowAttrib(drawData.window, GLFW_DECORATED, !appData.settings.docked);
	ShowWindow(drawData.window_handle, SW_HIDE);
	SetWindowLongPtr(drawData.window_handle, GWL_EXSTYLE, appData.settings.docked ? WS_EX_TOOLWINDOW : 0);
	ShowWindow(drawData.window_handle, SW_SHOW);
}

void setAutostart(bool newValue)
{
	const size_t MAX_PATH_LENGTH = 2048;
	const wchar_t* KEY_APP_NAME = L"AsuroTool";

	HRESULT hr;

	HKEY runKey = nullptr;
	hr = RegCreateKey(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", &runKey);
	if (isError(hr, "Failed to find/create autostart run key: ")) return;

	if (newValue)
	{
		std::wstring appPath;
		if (FAILED(getAppPath(appPath))) return;

		hr = RegSetValueEx(runKey, KEY_APP_NAME, 0, REG_SZ, (BYTE*)appPath.c_str(), static_cast<DWORD>((appPath.size() + 1) * sizeof(wchar_t)));
		if (isError(hr, "Failed to write autostart key: ")) return;
	}
	else
	{
		hr = RegDeleteValue(runKey, KEY_APP_NAME);
		if (isError(hr, "Failed to delete autostart key: ")) return;
	}
}

void loadUiStyle()
{
	ImGuiStyle& style = ImGui::GetStyle();
	style.WindowPadding = { 6.f, 12.f };
	style.WindowBorderSize = 0.f;

	style.FramePadding = { 8.f, 4.f };

	style.ItemSpacing = { 6.f, 4.f };
	style.GrabRounding = 2.f;
	style.PopupBorderSize = 4.f;

	ImVec4* colors = style.Colors;
	colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
	colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
	colors[ImGuiCol_WindowBg] = ImVec4(0.10f, 0.07f, 0.09f, 0.99f);
	colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
	colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.04f, 0.07f, 1.00f);
	colors[ImGuiCol_Border] = ImVec4(0.14f, 0.10f, 0.13f, 0.99f);
	colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
	colors[ImGuiCol_FrameBg] = ImVec4(0.02f, 0.01f, 0.01f, 0.54f);
	colors[ImGuiCol_FrameBgHovered] = ImVec4(0.98f, 0.36f, 0.36f, 0.40f);
	colors[ImGuiCol_FrameBgActive] = ImVec4(0.60f, 0.41f, 0.41f, 0.67f);
	colors[ImGuiCol_TitleBg] = ImVec4(0.04f, 0.04f, 0.04f, 1.00f);
	colors[ImGuiCol_TitleBgActive] = ImVec4(0.48f, 0.16f, 0.16f, 1.00f);
	colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.02f, 0.02f, 0.02f, 0.51f);
	colors[ImGuiCol_MenuBarBg] = ImVec4(0.06f, 0.05f, 0.06f, 0.99f);
	colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.53f);
	colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f);
	colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
	colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f);
	colors[ImGuiCol_CheckMark] = ImVec4(0.98f, 0.61f, 0.26f, 1.00f);
	colors[ImGuiCol_SliderGrab] = ImVec4(0.88f, 0.38f, 0.24f, 1.00f);
	colors[ImGuiCol_SliderGrabActive] = ImVec4(0.98f, 0.41f, 0.26f, 1.00f);
	colors[ImGuiCol_Button] = ImVec4(0.21f, 0.11f, 0.17f, 1.00f);
	colors[ImGuiCol_ButtonHovered] = ImVec4(0.30f, 0.15f, 0.25f, 1.00f);
	colors[ImGuiCol_ButtonActive] = ImVec4(0.47f, 0.23f, 0.39f, 1.00f);
	colors[ImGuiCol_Header] = ImVec4(0.46f, 0.19f, 0.12f, 0.67f);
	colors[ImGuiCol_HeaderHovered] = ImVec4(0.69f, 0.29f, 0.19f, 0.80f);
	colors[ImGuiCol_HeaderActive] = ImVec4(0.98f, 0.41f, 0.26f, 1.00f);
	colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.45f, 0.43f, 0.50f);
	colors[ImGuiCol_SeparatorHovered] = ImVec4(0.75f, 0.24f, 0.10f, 0.78f);
	colors[ImGuiCol_SeparatorActive] = ImVec4(0.75f, 0.24f, 0.10f, 1.00f);
	colors[ImGuiCol_ResizeGrip] = ImVec4(0.98f, 0.41f, 0.26f, 0.20f);
	colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.98f, 0.41f, 0.26f, 0.67f);
	colors[ImGuiCol_ResizeGripActive] = ImVec4(0.98f, 0.41f, 0.26f, 0.95f);
	colors[ImGuiCol_Tab] = ImVec4(0.09f, 0.02f, 0.07f, 0.86f);
	colors[ImGuiCol_TabHovered] = ImVec4(0.28f, 0.15f, 0.24f, 1.00f);
	colors[ImGuiCol_TabActive] = ImVec4(0.37f, 0.14f, 0.29f, 1.00f);
	colors[ImGuiCol_TabUnfocused] = ImVec4(0.33f, 0.21f, 0.28f, 1.00f);
	colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.42f, 0.20f, 0.14f, 1.00f);
	colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
	colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
	colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
	colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
	colors[ImGuiCol_TableHeaderBg] = ImVec4(0.25f, 0.10f, 0.10f, 1.00f);
	colors[ImGuiCol_TableBorderStrong] = ImVec4(0.31f, 0.31f, 0.35f, 1.00f);
	colors[ImGuiCol_TableBorderLight] = ImVec4(0.23f, 0.23f, 0.25f, 1.00f);
	colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
	colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f);
	colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
	colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
	colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
	colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
	colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
	colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
}