#include "GlfwWindowManager.h"

#include "utilities/Logger.h"

GlfwWindowManager::GlfwWindowManager()
{
}

GlfwWindowManager::~GlfwWindowManager()
{
}

void GlfwWindowManager::Initialize(const FWindowConfig& Config)
{
	if (IsInitialized())
	{
		return;
	}

	this->Config = Config;

	InitializeGlfw();
}

void GlfwWindowManager::Cleanup()
{
	if (!IsInitialized())
	{
		Log::Warning("Not initialized");
		return;
	}

	DestroyWindow();

	glfwTerminate();
}

bool GlfwWindowManager::ShouldClose() const
{
	return Window && glfwWindowShouldClose(Window);
}

void GlfwWindowManager::PollEvents()
{
	if (Window)
	{
		glfwPollEvents();
	}
}

void GlfwWindowManager::WaitEvents() const
{
	if (Window)
	{
		glfwWaitEvents();
	}
}

void GlfwWindowManager::SetTitle(const std::string& Title)
{
	// this->Title = Title;

	if (Window)
	{
		glfwSetWindowTitle(Window, Title.c_str());
	}
}

void GlfwWindowManager::SetResizeCallback(GLFWwindowsizefun Callback)
{
	if (Window)
	{
		glfwSetWindowSizeCallback(Window, Callback);
	}
}

void GlfwWindowManager::SetKeyCallback(GLFWkeyfun Callback)
{
	if (Window)
	{
		glfwSetKeyCallback(Window, Callback);
	}
}

void GlfwWindowManager::SetMouseButtonCallback(GLFWmousebuttonfun Callback)
{
	if (Window)
	{
		glfwSetMouseButtonCallback(Window, Callback);
	}
}

void GlfwWindowManager::SetCursorPositionCallback(GLFWcursorposfun Callback)
{
	if (Window)
	{
		glfwSetCursorPosCallback(Window, Callback);
	}
}

void GlfwWindowManager::SetScrollCallback(GLFWscrollfun Callback)
{
	if (Window)
	{
		glfwSetScrollCallback(Window, Callback);
	}
}

void GlfwWindowManager::DestroyWindow()
{
	if (Window)
	{
		glfwDestroyWindow(Window);
		Window = nullptr;
	}
}

void GlfwWindowManager::InitializeGlfw()
{
	if (!IsInitialized())
	{
		if (!glfwInit())
		{
			Log::Error("Failed to initialize GLFW");
		}
	}

	glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_NATIVE_CONTEXT_API);
	glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
	glfwWindowHint(GLFW_RESIZABLE, Config.bResizable ? GLFW_TRUE : GLFW_FALSE);
	glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE);
	glfwWindowHint(GLFW_DECORATED, GLFW_TRUE);
	glfwWindowHint(GLFW_FOCUSED, GLFW_TRUE);
	glfwWindowHint(GLFW_AUTO_ICONIFY, GLFW_FALSE);
	glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);

	glfwWindowHintString(GLFW_WAYLAND_APP_ID, Config.Title.c_str());

	Window = glfwCreateWindow(
		Config.Width,
		Config.Height,
		Config.Title.c_str(),
		Config.bFullscreen ? glfwGetPrimaryMonitor() : nullptr,
		nullptr);

	if (!Window)
	{
		Log::Error("Failed to create GLFW window");
	}
	else
	{
		Log::Info("Created GLFW window successfully.");
	}

	glfwSetWindowSize(Window, Config.Width, Config.Height);
	const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
	if (mode)
	{
		int xPos = (mode->width - Config.Width) / 2;
		int yPos = (mode->height - Config.Height) / 2;
		glfwSetWindowPos(Window, xPos, yPos);
	}
}
