#pragma once

#include "client/Client.h"
#include "client/display/PlayerController.h"
#include "client/render/BulletRenderer.h"
#include "client/render/Camera.h"
#include "client/render/loader/GLLoader.h"
#include "client/render/loader/ModelLoader.h"

namespace blitz {

namespace shader {

class EntityShader;
class WorldShader;
class GunShader;

}  // namespace shader


namespace render {

class MainRenderer : public game::ClientListener, public game::PlayerInputListener {
  private:
	Client* m_Client;
	ModelLoader::Model m_PlayerModel;
	ModelLoader::Model m_WorldModel;
	ModelLoader::Model m_GunModel;
	std::unique_ptr<shader::EntityShader> m_EntityShader;
	std::unique_ptr<shader::WorldShader> m_WorldShader;
	std::unique_ptr<shader::GunShader> m_GunShader;
	input::PlayerController m_PlayerController;
	unsigned int m_Texture;
	float m_ShootTime;
	Camera m_Camera;
	BulletRenderer m_BulletRenderer;

  public:
	MainRenderer(Client* client);
	~MainRenderer();

	virtual void OnSpectatorChange(game::PlayerID player) override;
	virtual void OnPlayerShoot(game::PlayerID player, const Vec3f& position, float yaw, float pitch) override;
	virtual void OnLocalPlayerShoot(const Vec3f& position, float yaw, float pitch) override;

	virtual void OnGameConfigUpdate() override;

	void Update();
	void Render();
	void RenderEntity(const GL::VertexArray& vao, const Vec3f& position, float yaw);
	void RenderWorld(const GL::VertexArray& vao);
	void RenderGun();

  private:
	void LoadModels();
	void RenderPlayers();
	void RenderWorld();
};

}  // namespace render
}  // namespace blitz
