#pragma once

#include <vector>
#include <Utils/SortedCollection.h>
#include "../Assets/Map.h"
#include <Gaming/Map2D.h>
#include "../Animator.h"

namespace mechanics
{

	class Object;
	class Map;

	struct PointInfo {
		PointInfo() : walkable(false), buildable(false), inSight(false), revealed(false), townCenter(false), denArea(false),
			movementModifier(0), object(NULL) {}

		bool walkable;
		bool buildable;
		bool inSight;
		bool revealed;
		bool townCenter;
		bool denArea;

		float movementModifier;
		mechanics::Object *object;

		bool AccessibleFrom(const PointInfo &pi) const {
			return walkable;
		}

		bool AccessibleByFrom(Object &object, const gaming::Map2D<PointInfo> &map, gge::utils::Point p, const PointInfo &pi) const;
	};

	static std::ostream &operator <<(std::ostream &out, const PointInfo &info)
	{
		out<<info.buildable;
		return out;
	}

	class MapEvent {
	public:
		MapEvent() : animation(NULL), isTriggered(false) {}

		std::string title;
		std::string text;
		Animator *animation;

		bool isTriggered;
	};

	class TimerEvent : public MapEvent {
	public:
		unsigned target;
	};

	class RevealedEvent : public MapEvent {
	public:

		gge::utils::Point location;

	};

	class DestroyedEvent : public MapEvent {
	public:

		mechanics::Object *object;

	};

	class Map
	{
	public:
		Map(assets::Map &given_provider);
		static Map &current() { return *currentMap; }
		static void current(Map &given_map) { 
			gge::utils::CheckAndDelete(currentMap);
			currentMap = &given_map; 
		}
		gge::utils::SortedCollection<Object> &getObjects() { return objects; }
		gaming::Map2D<PointInfo> &getPointInfoMap() { return pointInfoMap; }

		assets::Map &provider() {
			return mProvider;
		}

		std::vector<TimerEvent> timerEvents;
		std::vector<RevealedEvent> revealedEvents;
		std::vector<DestroyedEvent> destroyedEvents;

	private:
		assets::Map &mProvider;
		gge::utils::SortedCollection<Object> objects;
		static Map *currentMap;

		gaming::Map2D<PointInfo> pointInfoMap;
	};



}
