#include "Utilities.h"
#include "../Main/Main.h"

#include <iostream>

std::unique_ptr<Misc::CUtilities> Misc::Utilities = std::make_unique<Misc::CUtilities>();

using namespace Misc;

void CUtilities::Console_Create(std::string title)
{
	AllocConsole();
	AttachConsole(GetCurrentProcessId());
	freopen_s(&m_pOutputFile, "CONOUT$", "w", stdout);
	m_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleTitleA(title.c_str());
}

void CUtilities::Console_Close()
{
	if (!m_pOutputFile || !m_hOutput || m_hOutput == INVALID_HANDLE_VALUE)
		return;

	fclose(m_pOutputFile);
	SetStdHandle(STD_OUTPUT_HANDLE, m_hOldOutput);
	FreeConsole();
}

void CUtilities::Console_Log(const char* text, ...)
{
	if (!text)
		return;

	va_list va_args;
	char buffer[2048] = { 0 };
	va_start(va_args, text);
	_vsnprintf_s(buffer, sizeof(buffer), text, va_args);
	va_end(va_args);
	std::cout << "[ GamesenseMenuFramework ] ";
	std::cout << ": " << buffer << std::endl;
}

void CUtilities::Console_SetTitle(std::string title)
{
	SetConsoleTitleA(title.c_str());
}

bool CUtilities::IsAnyMouseDown()
{
	for (int n = 0; n < sizeof(this->MouseDown); n++)
		if (this->MouseDown[n])
			return true;
	return false;
}

LRESULT CUtilities::WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	int dbutton = 0;
	int ubutton = 0;
	switch (msg)
	{
	case WM_LBUTTONDOWN:
		dbutton = 0; break;
	case WM_RBUTTONDOWN:
		dbutton = 1; break;
	case WM_MBUTTONDOWN:
		dbutton = 2; break;
	case WM_XBUTTONDOWN:
	{
		if (LOWORD(wParam) == MK_XBUTTON1)
			dbutton = 3;
		if (LOWORD(wParam) == MK_XBUTTON2)
			dbutton = 4;

		if (!this->IsAnyMouseDown() && GetCapture() == NULL)
			SetCapture(hwnd);

		this->MouseDown[dbutton] = true;
		return true;
	}
	case WM_LBUTTONUP:
		ubutton = 0;
	case WM_RBUTTONUP:
		ubutton = 1;
	case WM_MBUTTONUP:
		ubutton = 2;
	case WM_XBUTTONUP:
	{
		if (LOWORD(wParam) == MK_XBUTTON1)
			ubutton = 3;
		if (LOWORD(wParam) == MK_XBUTTON2)
			ubutton = 4;

		this->MouseDown[ubutton] = false;
		if (!this->IsAnyMouseDown() && GetCapture() == hwnd)
			ReleaseCapture();
		return true;
	}
	case WM_MOUSEWHEEL:
		return true;
	case WM_MOUSEMOVE:
		return false;
	case WM_KEYDOWN:
	case WM_SYSKEYDOWN:
		if (wParam < 256)
			this->KeysDown[wParam] = 1;

		return false;
	case WM_KEYUP:
	case WM_SYSKEYUP:
		if (wParam < 256)
			this->KeysDown[wParam] = 0;

		return false;
	case WM_CHAR:
		return true;
	case WM_SETCURSOR:

		if (LOWORD(lParam) == HTCLIENT)
			return 1;

		return false;
	}
	return 0;
}

float CUtilities::GetDeltaTime() {
	return GetStandaloneDeltaTime();
}
