#pragma once

#include "td/game/World.h"

#include "client/render/Renderer.h"
#include "client/render/VertexCache.h"

#include "client/render/gui/TowerPlacePopup.h"
#include "client/render/gui/TowerUpgradePopup.h"
#include "client/render/gui/MobTooltip.h"
#include "client/render/gui/CastleTooltip.h"

namespace td {

namespace client {

class ClientGame;

} // namespace client

namespace render {

class WorldRenderer : public game::WorldListener {
private:
	client::ClientGame* m_Client;
	Renderer* m_Renderer;
	game::World* m_World;
	std::unique_ptr<GL::VertexArray> m_WorldVao, m_MobVao, m_SelectTileVao;
	Vec2f m_CamPos;
	Vec2f m_CursorPos;
	Vec2f m_HoldCursorPos;
	Vec2f m_LastClicked;
	float m_Zoom;
	float m_CamSensibility = 1;
	bool m_PopupOpened = false;
	VertexCache m_TowersCache;

	std::unique_ptr<gui::TowerPlacePopup> m_TowerPlacePopup;
	std::unique_ptr<gui::TowerUpgradePopup> m_TowerUpgradePopup;
	std::unique_ptr<gui::MobTooltip> m_MobTooltip;
	std::unique_ptr<gui::CastleTooltip> m_CastleTooltip;
public:
	WorldRenderer(game::World* world, client::ClientGame* client);
	~WorldRenderer();

	void LoadModels();

	void Update();
	void Render();

	void ResetCam();
	void SetCamPos(float camX, float camY);

	void MoveCam(float relativeX, float relativeY);
	void ChangeZoom(float zoom);

	// WorldListener

	virtual void OnTowerAdd(game::TowerPtr tower);
	virtual void OnTowerRemove(game::TowerPtr tower);
private:
	void Click();
	void RenderWorld() const;
	void RenderTowers() const;
	void RenderMobs() const;
	void RenderTileSelect() const;
	void RenderPopups();
	void RenderMobTooltip() const;
	void RenderCastleTooltip() const;
	void DetectClick();
	void DetectMobHovering() const;
	void DetectCastleHovering() const;
	void RenderTooltips() const;
	void RemoveTower();
	Vec2f GetCursorWorldPos() const;
	Vec2f GetClickWorldPos() const;

	void UpdateCursorPos();
};

} // namespace render
} // namespace td
