#include "Monster.h"
#include "DamageNumber.h"

extern std::map<AnimationState,Animate2D::FrameSequence>ANIMATION_DATA;
extern std::map<MonsterName,MonsterData>MONSTER_DATA;
extern std::vector<Monster>MONSTER_LIST;
extern std::vector<DamageNumber>DAMAGENUMBER_LIST;

MonsterData::MonsterData(){}
MonsterData::MonsterData(MonsterName type,int hp,int atk,std::vector<AnimationState>animations,float moveSpd,float size,MonsterStrategy strategy):
	type(type),hp(hp),atk(atk),moveSpd(moveSpd),size(size),strategy(strategy),animations(animations){
}
int MonsterData::GetHealth(){
	return hp;
}
int MonsterData::GetAttack(){
	return atk;
}
float MonsterData::GetMoveSpdMult(){
	return moveSpd;
}
float MonsterData::GetSizeMult(){
	return size;
}
MonsterName MonsterData::GetType(){
	return type;
}
MonsterStrategy MonsterData::GetAIStrategy(){
	return strategy;
}

Monster::Monster(){}
Monster::Monster(vf2d pos,MonsterData data):
	pos(pos),hp(data.GetHealth()),maxhp(data.GetHealth()),atk(data.GetAttack()),moveSpd(data.GetMoveSpdMult()),size(data.GetSizeMult()),strategy(data.GetAIStrategy()),type(data.GetType()){
	bool firstAnimation=true;
	for(AnimationState&anim:data.GetAnimations()){
		animation.AddState(anim,ANIMATION_DATA[anim]);
		if(firstAnimation){
			animation.ChangeState(internal_animState,anim);
			firstAnimation=false;
		}
	}
	randomFrameOffset=(rand()%1000)/1000.f;
}
vf2d&Monster::GetPos(){
	return pos;
}
int Monster::GetHealth(){
	return hp;
}
int Monster::GetAttack(){
	return atk;
}
float Monster::GetMoveSpdMult(){
	return moveSpd;
}
float Monster::GetSizeMult(){
	return size;
}
Animate2D::Frame Monster::GetFrame(){
	return animation.GetFrame(internal_animState);
}
void Monster::UpdateAnimation(AnimationState state){
	animation.ChangeState(internal_animState,state);
}
bool Monster::Update(float fElapsedTime){
	switch(strategy){
		RUN_TOWARDS:{
			
		}break;
		SHOOT_AFAR:{
			
		}break;
	}
	if(hp<=0){
		deathTimer+=fElapsedTime;
		if(deathTimer>3){
			return false;
		}
	}
	animation.UpdateState(internal_animState,randomFrameOffset+fElapsedTime);
	randomFrameOffset=0;
	return true;
}
AnimationState Monster::GetDeathAnimationName(){
	switch(type){
		case SLIME_GREEN:{
			return AnimationState::GREEN_SLIME_DIE;
		}
		case SLIME_BLUE:{
			return AnimationState::BLUE_SLIME_DIE;
		}
		case SLIME_RED:{
			return AnimationState::RED_SLIME_DIE;
		}
		default:{
			return AnimationState::IDLE_S;
		}
	}
}
void Monster::Hurt(int damage){
	hp=std::max(0,hp-damage);
	DAMAGENUMBER_LIST.push_back(DamageNumber(pos,damage));
	if(hp<=0){
		animation.ChangeState(internal_animState,GetDeathAnimationName());
	}
}

bool Monster::IsAlive(){
	return hp>0;
}

MonsterSpawner::MonsterSpawner(){}
MonsterSpawner::MonsterSpawner(vf2d pos,int range,std::vector<std::pair<MonsterName,vf2d>>monsters):
	pos(pos),range(range),monsters(monsters){
}
bool MonsterSpawner::SpawnTriggered(){
	return triggered;
}
int MonsterSpawner::GetRange(){
	return range;
}
vf2d MonsterSpawner::GetPos(){
	return pos;
}
void MonsterSpawner::SetTriggered(bool trigger,bool spawnMonsters){
	triggered=trigger;
	if(spawnMonsters){
		for(std::pair<MonsterName,vf2d>&monsterInfo:monsters){
			MONSTER_LIST.push_back(Monster(pos+monsterInfo.second,MONSTER_DATA[monsterInfo.first]));
		}
	}
}