#pragma once

#include "td/Defines.h"
#include <memory>
#include "loader/GLLoader.h"
#include "client/render/shaders/WorldShader.h"
#include "client/render/shaders/EntityShader.h"

namespace td {
namespace render {

struct Camera {
	Mat4f viewMatrix;
	Mat4f projectionMatrix;
	Mat4f InvViewMatrix;
	Mat4f InvProjectionMatrix;

	float CamDistance = 25.0f;
	Vec3f CamPos {0, CamDistance, 0};
	Vec2f CamLook {};

	float m_Yaw = -PI / 2.0f;
	float m_Pitch = -PI / 2.0f + 0.0000001f;
};

class Renderer {
public:
	static constexpr float m_AnimationSpeed = 2.0f;
	static constexpr float m_MouseSensitivity = 200.0f;

	struct Model {
		GL::VertexArray* vao;
		Vec3f positon;
		Vec3f color = { 1, 1, 1 };
	};
private:
	std::unique_ptr<shader::WorldShader> m_WorldShader;
	std::unique_ptr<shader::EntityShader> m_EntityShader;

	Vec2i m_WindowSize;

	Vec3f m_BackgroundColor;

	Camera m_Camera {};
public:
	Renderer();
	~Renderer();

	bool Init();

	void Prepare();
	void Resize(const int width, const int height);

	void RenderVAO(const GL::VertexArray& vao);
	void RenderModel(const Model& model);

	void AddZoom(float zoom);
	void SetCamAngularMovement(const Vec2f& mov);
	void SetCamMovement(const Vec2f& lastCursorPos, const Vec2f& currentCursorPos);
	void SetCamLook(const Vec2f& worldPos);
	void ResetCamLook();

	void SetBackgroundColor(const Vec3f& color) { m_BackgroundColor = color; }

	Vec2f GetCursorWorldPos(const Vec2f& cursorPos, float windowWidth, float windowHeight);
private:
	void InitShaders();
	void SetCamPos(const Vec3f& newPos);
};

} // namespace render
} // namespace td
