#pragma once

#include "game/World.h"

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

#include "render/gui/TowerPlacePopup.h"
#include "render/gui/MobTooltip.h"

#include "render/gui/imgui/imgui.h"

#include <glm/glm.hpp>

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;
    glm::vec2 m_CamPos;
    glm::vec2 m_CursorPos;
    glm::vec2 m_HoldCursorPos;
    glm::vec2 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::MobTooltip> m_MobTooltip;
public:
    WorldRenderer(game::World* world, client::ClientGame* client);
    ~WorldRenderer();

    void loadModels();

    static ImVec4 getImGuiTeamColor(game::TeamColor color);

    void update();
    void render();

    void setCamPos(float camX, float camY);

    void moveCam(float relativeX, float relativeY, float aspectRatio);
    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 renderTowerUpgradePopup();
    void renderMobTooltip() const;
    void detectClick();
    void detectMobHovering() const;
    glm::vec2 getCursorWorldPos() const;
    glm::vec2 getClickWorldPos() const;

    void updateCursorPos();
};

} // namespace render
} // namespace td
