#include "Map.h"
#include "../Assets/Map.h"
#include "../Assets/Tile.h"
#include "../Assets/Object.h"
#include "../Graphics/Animation.h"
#include "Mover.h"

namespace mechanics {
	Map *Map::currentMap = NULL;

	Map::Map(assets::Map &given_provider): mProvider(given_provider), pointInfoMap(given_provider.tileMap.GetSize()) {
		mProvider.tileMap.ForAllCells([&](const gge::utils::Point &location, assets::Tile *tile) {

			pointInfoMap(location).walkable = !tile->forceNotWalkable && tile->parent->isWalkable;
			pointInfoMap(location).buildable = false;
			pointInfoMap(location).movementModifier = tile->parent->movementModifier;
			pointInfoMap(location).object=NULL;
			pointInfoMap(location).inSight=false;
			pointInfoMap(location).townCenter=false;
			pointInfoMap(location).denArea=false;
			pointInfoMap(location).revealed=false;
		});

		for(auto it=mProvider.events.begin();it!=mProvider.events.end();++it) {
			if(it->type==Timer) {
				timerEvents.push_back(TimerEvent());
				TimerEvent &t=timerEvents.back();

				std::stringstream ss(it->condition);

				ss>>t.target;
				t.title=it->title;
				t.text=it->text;
				
				if(assets::AnimationProvider::list[it->imageID]) {
					t.animation=new graphics::Animation(*assets::AnimationProvider::list[it->imageID]);
				}
			}
			else if(it->type==Revealed) {
				revealedEvents.push_back(RevealedEvent());
				RevealedEvent &l=revealedEvents.back();

				std::stringstream ss(it->condition);

				ss>>l.location;
				l.title=it->title;
				l.text=it->text;

				if(assets::AnimationProvider::list[it->imageID]) {
					l.animation=new graphics::Animation(*assets::AnimationProvider::list[it->imageID]);
				}
			}
		}
	}

	bool PointInfo::AccessibleByFrom(Object &object, const gaming::Map2D<PointInfo> &map, gge::utils::Point p, const PointInfo &pi) const {
		if(walkable) return true; //no problem
		if(this->object==&object) return true; //this is us no problem

		if(dynamic_cast<Mover*>(this->object)) { //if the target object is a mover
			auto *mover=dynamic_cast<Mover*>(this->object);
			if(object.currentLocation().Distance(this->object->currentLocation())>8) {//too far ignore their presence
				return true;
			}
			else if(object.currentLocation().Distance(this->object->currentLocation())>2 && mover->isMoving()) { //he is moving
				return true;
			}
		}

		return false;
	}

}
