#include <string>

#include "Human.h"
#include "Artisan.h"
#include "../Graphics/Animation.h"
#include "../Assets/Artisan.h"
#include "PlayerGame.h"
#include "Weapons/MeleeWeapon.h"
#include "../Assets/Item.h"
#include "Armors/BodyArmor.h"
#include "MilitaryBuilding.h"

namespace mechanics {

	Artisan::Artisan(Human &generatefrom, const std::string &type, Animator &cloth) : Human(generatefrom.animator, generatefrom.animatorHair, OwnerType::player, generatefrom.gender()), 
		mType(type), mCrafting(NULL)
	{
		mStat = generatefrom.stat();
		mLevel = generatefrom.level();
		mXp = generatefrom.xp();
		mName = generatefrom.name();
		mSurname = generatefrom.surname();

		//check if cloth for artisan exists
		if(assets::AnimationProvider::list[type+"_cloth"])
		{
			this->cloth=new graphics::Animation(*assets::AnimationProvider::list[type+"_cloth"]);
			delete &cloth;
		}
		else {
			this->cloth=&cloth;
		}

		setAnimation(South, "Stand");
		log("Ready...");

		levelUp();
	}

	void Artisan::beginCrafting(std::string ID) {
		mCrafting=assets::Item::list[ID];
		PlayerGame::current().ConsumeGold(mCrafting->cost);

		float crafttime = mCrafting->craftTime;
		crafttime -= (spe() * mCrafting->craftTimeSpeModifier) - (level() * mCrafting->precisionLvlModifier);


		if(mCrafting->requiredBuilding.size()) {
			std::string target=gge::utils::Random(mCrafting->requiredBuilding);
			for(auto it=PlayerGame::current().getMilitaryBuildingList().begin();it!=PlayerGame::current().getMilitaryBuildingList().end();++it) {
				if((*it)->provider().ID==target) {
					moveTo( (*it)->provider().usablePoints[0]+(*it)->currentLocation() );
				}
			}
		}

		mTotal=crafttime;
		mFinish=currentGameTime+mTotal;
	}

	void Artisan::checkCraft() {
		if(mCrafting && currentGameTime>=mFinish) {
			StorageBuilding *storage=NULL;
			for(unsigned j=0;j<PlayerGame::current().getMilitaryBuildingList().size();j++) {
				if(dynamic_cast<StorageBuilding*>(PlayerGame::current().getMilitaryBuildingList()[j])) {
					auto mb=dynamic_cast<StorageBuilding*>(PlayerGame::current().getMilitaryBuildingList()[j]);
					if(mb->storageType()==mCrafting->type) {
						if(mb->isAvailable()) {
							storage=mb;
							break;
						}
					}
				}
			}

			if(!storage) {
				log("Cannot store item!");
				setAnimation(North, "No", false);
				mFinish+=assets::constants::general::retryDelay; //!Constant, retry delay
				return;
			}

			auto item=createItem(mCrafting->ID);

			PlayerGame::current().addItem(*item);
			storage->store(item);

			moveTo( storage->provider().usablePoints[0]+storage->currentLocation());

			increaseXP(item->provider().XPReward);

			log(mCrafting->ID + " crafted");

			mCrafting=NULL;
		}
	}

	void Artisan::checkAction() {
		Human::checkAction();

		checkCraft();
	}

	void Artisan::Killed(Attacker *attacker, BaseWeapon *weapon) {
		Human::Killed(attacker, weapon);
		PlayerGame::current().destroyArtisan(this);

		Map::current().getPointInfoMap()(location).walkable=true;
		Map::current().getPointInfoMap()(location).object=NULL;
	}


	unsigned Artisan::lastPaymentCheck() const {
		return mLastPaymentCheck;
	}

	void Artisan::lastPaymentCheck(unsigned value) {
		mLastPaymentCheck = value;
	}

}