#ifndef _H_SCENE_H
#define _H_SCENE_H

#include <span>
#include <unordered_map>
#include <memory>

#include <gameplay/gameactor.h>

class Background;
class Entity;
class Camera;
class Map;
class ResourceManager;
class Renderer;
class EventManager;
class Line;
class PhysicsEngine;
class Sprite;
class Shader;

struct SceneData;

enum SceneType {
	SCENE_STORY,
	SCENE_SHOOTER
};

class ISceneContext {
public:
	virtual std::weak_ptr<EventManager> getEventManager() = 0;
	virtual std::weak_ptr<EventManager> getGlobalEventManager() = 0;
	virtual std::span<std::weak_ptr<GameActor>> getAllEntities() const = 0;
	virtual unsigned int getPlayerID() const = 0;
};

class Scene : public ISceneContext, public std::enable_shared_from_this<Scene>
{
public:
	Scene(SceneType type, std::shared_ptr<ResourceManager> resources, std::weak_ptr<EventManager> globalEvents);

	void init();

	void update(double deltaTime);
	void render(std::shared_ptr<Renderer> renderer);

	std::shared_ptr<GameActor> getPlayer() const;
	unsigned int getPlayerID() const override { return player->getEntityID(); }

	std::weak_ptr<EventManager> getEventManager() override { return eventManager; }
	std::weak_ptr<EventManager> getGlobalEventManager() override { return globalEventManager; }
	std::span<std::weak_ptr<GameActor>> getAllEntities() const override;

	void unloadScene();

protected:
	void loadDebugShooterScene();
	void loadDebugStoryScene() { /*not implemented yet*/ }

private:

	void hookSceneEvents();
	GameActor* getGameActorByID(const unsigned int ID);

	// Non-owning pointer DO NOT DELETE, resource manager will handle that!
	Background *background;

	SceneType type;
	std::shared_ptr<Map> map;
	//std::shared_ptr<TileSet> tileSet;
	std::shared_ptr<GameActor> player;
	std::unordered_map<unsigned int, std::shared_ptr<GameActor>> entities;
	mutable std::vector<std::weak_ptr<GameActor>> entityCache;
	std::shared_ptr<Camera> camera;
	std::shared_ptr<PhysicsEngine> physicsEngine;

	std::shared_ptr<Line> debugLine;
	std::shared_ptr<ResourceManager> resourceManager;
	std::weak_ptr<EventManager> globalEventManager;
	std::shared_ptr<EventManager> eventManager;
	const SceneData* sceneData;
};

#endif //_H_SCENE_H
