#include "client/render/Camera.h"

#include "blitz/misc/Log.h"
#include "blitz/misc/Maths.h"
#include "imgui.h"
#include <algorithm>

namespace blitz {
namespace render {

void Camera::Update(float delta) {
	if (ImGui::GetIO().MouseDown[0]) {
		// slower when more fps. why ?
		m_Yaw += ImGui::GetIO().MouseDelta.x * delta * 0.2f;
		m_Pitch -= ImGui::GetIO().MouseDelta.y * delta * 0.2f;
		m_Pitch = std::clamp(m_Pitch, -maths::PI / 2.0f + 0.001f, maths::PI / 2.0f - 0.001f);
	}

	static float SpeedFactor = 10.0f;
	float Speed = SpeedFactor * delta;

	if (!ImGui::GetIO().WantCaptureKeyboard) {
		if (ImGui::IsKeyDown(ImGuiKey_Z)) {
			m_Position += {std::cos(m_Yaw) * Speed, 0, std::sin(m_Yaw) * Speed};
		} else if (ImGui::IsKeyDown(ImGuiKey_S)) {
			m_Position -= {std::cos(m_Yaw) * Speed, 0, std::sin(m_Yaw) * Speed};
		}

		if (ImGui::IsKeyDown(ImGuiKey_Q)) {
			m_Position += {std::sin(m_Yaw) * Speed, 0, -std::cos(m_Yaw) * Speed};
		} else if (ImGui::IsKeyDown(ImGuiKey_D)) {
			m_Position -= {std::sin(m_Yaw) * Speed, 0, -std::cos(m_Yaw) * Speed};
		}
	}

	int windowWidth = ImGui::GetIO().DisplaySize.x;
	int windowHeight = ImGui::GetIO().DisplaySize.y;

	if (windowWidth != m_LastWindowSize.x || windowHeight != m_LastWindowSize.y) {
		m_LastWindowSize = {windowWidth, windowHeight};

		m_PerspectiveMatrix =
			maths::Perspective(80.0f / 180.0f * maths::PI, static_cast<float>(windowWidth) / windowHeight, 0.1f, 160.0f);
	}
}

Mat4f Camera::GetViewMatrix() const {
	Vec3f front = {
		std::cos(m_Yaw) * std::cos(m_Pitch),
		std::sin(m_Pitch),
		std::sin(m_Yaw) * std::cos(m_Pitch),
	};

	return maths::Look(m_Position, front, {0, 1, 0});
}

}  // namespace render
}  // namespace blitz
