#include "Animation.h"
#include "Crawler.h"
#include "DEFINES.h"
#include "safemap.h"

INCLUDE_game
INCLUDE_ANIMATION_DATA
INCLUDE_DATA

void sig::Animation::InitializeAnimations(){

	auto CreateStillAnimation=[&](Renderable&img,vf2d size,std::string state,AnimationData data={}){
		Animate2D::FrameSequence anim(data.frameDuration,data.style);
		anim.AddFrame({&img,{{0,0},size}});
		ANIMATION_DATA[state]=anim;
	};

	auto CreateHorizontalAnimationSequence=[&](Renderable&img,int frameCount,vf2d size,std::string state,AnimationData data={}){
		Animate2D::FrameSequence anim(data.frameDuration,data.style);
		for(int i=0;i<frameCount;i++){
			anim.AddFrame({&img,{{int(i*size.x),0},size}});
		}
		ANIMATION_DATA[state]=anim;
	};

	auto SetupClassWalkIdleAnimations=[&](Renderable&sheet,std::string className){
		Animate2D::FrameSequence pl_walk_s{0.2};
		pl_walk_s.AddFrame({&sheet,{vi2d{0,0}*24,{24,24}}});
		pl_walk_s.AddFrame({&sheet,{vi2d{1,0}*24,{24,24}}});
		pl_walk_s.AddFrame({&sheet,{vi2d{0,0}*24,{24,24}}});
		pl_walk_s.AddFrame({&sheet,{vi2d{2,0}*24,{24,24}}});
		ANIMATION_DATA[className+"_WALK_S"]=pl_walk_s;
		Animate2D::FrameSequence pl_walk_e{0.2};
		pl_walk_e.AddFrame({&sheet,{vi2d{0,3}*24,{24,24}}});
		pl_walk_e.AddFrame({&sheet,{vi2d{1,3}*24,{24,24}}});
		pl_walk_e.AddFrame({&sheet,{vi2d{0,3}*24,{24,24}}});
		pl_walk_e.AddFrame({&sheet,{vi2d{2,3}*24,{24,24}}});
		ANIMATION_DATA[className+"_WALK_E"]=pl_walk_e;
		Animate2D::FrameSequence pl_walk_w{0.2};
		pl_walk_w.AddFrame({&sheet,{vi2d{0,2}*24,{24,24}}});
		pl_walk_w.AddFrame({&sheet,{vi2d{1,2}*24,{24,24}}});
		pl_walk_w.AddFrame({&sheet,{vi2d{0,2}*24,{24,24}}});
		pl_walk_w.AddFrame({&sheet,{vi2d{2,2}*24,{24,24}}});
		ANIMATION_DATA[className+"_WALK_W"]=pl_walk_w;
		Animate2D::FrameSequence pl_walk_n{0.2};
		pl_walk_n.AddFrame({&sheet,{vi2d{0,1}*24,{24,24}}});
		pl_walk_n.AddFrame({&sheet,{vi2d{1,1}*24,{24,24}}});
		pl_walk_n.AddFrame({&sheet,{vi2d{0,1}*24,{24,24}}});
		pl_walk_n.AddFrame({&sheet,{vi2d{2,1}*24,{24,24}}});
		ANIMATION_DATA[className+"_WALK_N"]=pl_walk_n;
		Animate2D::FrameSequence pl_idle_s;
		pl_idle_s.AddFrame({&sheet,{vi2d{0,0}*24,{24,24}}});
		ANIMATION_DATA[className+"_IDLE_S"]=pl_idle_s;
		Animate2D::FrameSequence pl_idle_e;
		pl_idle_e.AddFrame({&sheet,{vi2d{0,3}*24,{24,24}}});
		ANIMATION_DATA[className+"_IDLE_E"]=pl_idle_e;
		Animate2D::FrameSequence pl_idle_w;
		pl_idle_w.AddFrame({&sheet,{vi2d{0,2}*24,{24,24}}});
		ANIMATION_DATA[className+"_IDLE_W"]=pl_idle_w;
		Animate2D::FrameSequence pl_idle_n;
		pl_idle_n.AddFrame({&sheet,{vi2d{0,1}*24,{24,24}}});
		ANIMATION_DATA[className+"_IDLE_N"]=pl_idle_n;
	};

	//Warrior animations.
	SetupClassWalkIdleAnimations(game->GFX_Warrior_Sheet,"WARRIOR");
	Animate2D::FrameSequence pl_warrior_swing_s(0.05),pl_warrior_swing_n(0.05),pl_warrior_swing_e(0.05),pl_warrior_swing_w(0.05);
	Animate2D::FrameSequence pl_warrior_sonic_swing_s(0.1,Animate2D::Style::OneShot),pl_warrior_sonic_swing_n(0.1,Animate2D::Style::OneShot),pl_warrior_sonic_swing_e(0.1,Animate2D::Style::OneShot),pl_warrior_sonic_swing_w(0.1,Animate2D::Style::OneShot);
	for (int i=0;i<4;i++){
		pl_warrior_swing_s.AddFrame({&game->GFX_Warrior_Sheet,{vi2d{4+i,0}*24,{24,24}}});
		pl_warrior_sonic_swing_s.AddFrame({&game->GFX_Warrior_Sheet,{vi2d{4+i,4}*24,{24,24}}});
	}
	for (int i=0;i<4;i++){
		pl_warrior_swing_n.AddFrame({&game->GFX_Warrior_Sheet,{vi2d{4+i,1}*24,{24,24}}});
		pl_warrior_sonic_swing_n.AddFrame({&game->GFX_Warrior_Sheet,{vi2d{4+i,5}*24,{24,24}}});
	}
	for (int i=0;i<4;i++){
		pl_warrior_swing_w.AddFrame({&game->GFX_Warrior_Sheet,{vi2d{4+i,2}*24,{24,24}}});
		pl_warrior_sonic_swing_w.AddFrame({&game->GFX_Warrior_Sheet,{vi2d{4+i,6}*24,{24,24}}});
	}
	for (int i=0;i<4;i++){
		pl_warrior_swing_e.AddFrame({&game->GFX_Warrior_Sheet,{vi2d{4+i,3}*24,{24,24}}});
		pl_warrior_sonic_swing_e.AddFrame({&game->GFX_Warrior_Sheet,{vi2d{4+i,7}*24,{24,24}}});
	}
	ANIMATION_DATA["WARRIOR_SWINGSWORD_N"]=pl_warrior_swing_n;
	ANIMATION_DATA["WARRIOR_SWINGSWORD_E"]=pl_warrior_swing_e;
	ANIMATION_DATA["WARRIOR_SWINGSWORD_S"]=pl_warrior_swing_s;
	ANIMATION_DATA["WARRIOR_SWINGSWORD_W"]=pl_warrior_swing_w;
	ANIMATION_DATA["WARRIOR_SWINGSONICSWORD_N"]=pl_warrior_sonic_swing_n;
	ANIMATION_DATA["WARRIOR_SWINGSONICSWORD_E"]=pl_warrior_sonic_swing_e;
	ANIMATION_DATA["WARRIOR_SWINGSONICSWORD_S"]=pl_warrior_sonic_swing_s;
	ANIMATION_DATA["WARRIOR_SWINGSONICSWORD_W"]=pl_warrior_sonic_swing_w;

	//Ranger animations
	SetupClassWalkIdleAnimations(game->GFX_Ranger_Sheet,"RANGER");
	Animate2D::FrameSequence pl_ranger_shoot_s,pl_ranger_shoot_n,pl_ranger_shoot_e,pl_ranger_shoot_w;
	for(int i=0;i<3;i++){
		pl_ranger_shoot_s.AddFrame({&game->GFX_Ranger_Sheet,{vi2d{3+i,0}*24,{24,24}}});
		pl_ranger_shoot_n.AddFrame({&game->GFX_Ranger_Sheet,{vi2d{3+i,1}*24,{24,24}}});
		pl_ranger_shoot_e.AddFrame({&game->GFX_Ranger_Sheet,{vi2d{3+i,3}*24,{24,24}}});
		pl_ranger_shoot_w.AddFrame({&game->GFX_Ranger_Sheet,{vi2d{3+i,2}*24,{24,24}}});
	}
	ANIMATION_DATA["RANGER_SHOOT_S"]=pl_ranger_shoot_s;
	ANIMATION_DATA["RANGER_SHOOT_N"]=pl_ranger_shoot_n;
	ANIMATION_DATA["RANGER_SHOOT_E"]=pl_ranger_shoot_e;
	ANIMATION_DATA["RANGER_SHOOT_W"]=pl_ranger_shoot_w;

	//Wizard animations
	SetupClassWalkIdleAnimations(game->GFX_Wizard_Sheet,"WIZARD");
	Animate2D::FrameSequence pl_wizard_idle_attack_s;
	pl_wizard_idle_attack_s.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4,0}*24,{24,24}}});
	ANIMATION_DATA["WIZARD_IDLE_ATTACK_S"]=pl_wizard_idle_attack_s;
	Animate2D::FrameSequence pl_wizard_idle_attack_e;
	pl_wizard_idle_attack_e.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4,3}*24,{24,24}}});
	ANIMATION_DATA["WIZARD_IDLE_ATTACK_E"]=pl_wizard_idle_attack_e;
	Animate2D::FrameSequence pl_wizard_idle_attack_w;
	pl_wizard_idle_attack_w.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4,2}*24,{24,24}}});
	ANIMATION_DATA["WIZARD_IDLE_ATTACK_W"]=pl_wizard_idle_attack_w;
	Animate2D::FrameSequence pl_wizard_idle_attack_n;
	pl_wizard_idle_attack_n.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4,1}*24,{24,24}}});
	ANIMATION_DATA["WIZARD_IDLE_ATTACK_N"]=pl_wizard_idle_attack_n;
	Animate2D::FrameSequence pl_wizard_attack_s(0.2);
	for(int i=0;i<3;i++){
		pl_wizard_attack_s.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4+i,0}*24,{24,24}}});
		if(i==1){
			pl_wizard_attack_s.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4,0}*24,{24,24}}});
		}
	}
	ANIMATION_DATA["WIZARD_ATTACK_S"]=pl_wizard_attack_s;
	Animate2D::FrameSequence pl_wizard_attack_e(0.2);
	for(int i=0;i<3;i++){
		pl_wizard_attack_e.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4+i,3}*24,{24,24}}});
		if(i==1){
			pl_wizard_attack_e.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4,3}*24,{24,24}}});
		}
	}
	ANIMATION_DATA["WIZARD_ATTACK_E"]=pl_wizard_attack_e;
	Animate2D::FrameSequence pl_wizard_attack_w(0.2);
	for(int i=0;i<3;i++){
		pl_wizard_attack_w.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4+i,2}*24,{24,24}}});
		if(i==1){
			pl_wizard_attack_w.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4,2}*24,{24,24}}});
		}
	}
	ANIMATION_DATA["WIZARD_ATTACK_W"]=pl_wizard_attack_w;
	Animate2D::FrameSequence pl_wizard_attack_n(0.2);
	for(int i=0;i<3;i++){
		pl_wizard_attack_n.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4+i,1}*24,{24,24}}});
		if(i==1){
			pl_wizard_attack_n.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4,1}*24,{24,24}}});
		}
	}
	ANIMATION_DATA["WIZARD_ATTACK_N"]=pl_wizard_attack_n;
	Animate2D::FrameSequence pl_wizard_cast_s(0.1);
	for(int i=0;i<2;i++){
		pl_wizard_cast_s.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{7+i,0}*24,{24,24}}});
	}
	ANIMATION_DATA["WIZARD_CAST_S"]=pl_wizard_cast_s;
	Animate2D::FrameSequence pl_wizard_cast_e(0.1);
	for(int i=0;i<2;i++){
		pl_wizard_cast_e.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{7+i,3}*24,{24,24}}});
	}
	ANIMATION_DATA["WIZARD_CAST_E"]=pl_wizard_cast_e;
	Animate2D::FrameSequence pl_wizard_cast_n(0.1);
	for(int i=0;i<2;i++){
		pl_wizard_cast_n.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{7+i,1}*24,{24,24}}});
	}
	ANIMATION_DATA["WIZARD_CAST_N"]=pl_wizard_cast_n;
	Animate2D::FrameSequence pl_wizard_cast_w(0.1);
	for(int i=0;i<2;i++){
		pl_wizard_cast_w.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{7+i,2}*24,{24,24}}});
	}
	ANIMATION_DATA["WIZARD_CAST_W"]=pl_wizard_cast_w;

	CreateHorizontalAnimationSequence(game->GFX_Effect_GroundSlam_Back,5,{64,64},"GROUND_SLAM_ATTACK_BACK",{0.02,Animate2D::Style::OneShot});
	CreateHorizontalAnimationSequence(game->GFX_Effect_GroundSlam_Front,5,{64,64},"GROUND_SLAM_ATTACK_FRONT",{0.02,Animate2D::Style::OneShot});
	CreateHorizontalAnimationSequence(game->GFX_Battlecry_Effect,5,{84,84},"BATTLECRY_EFFECT",{0.02,Animate2D::Style::OneShot});
	CreateHorizontalAnimationSequence(game->GFX_SonicSlash,4,{60,60},"SONICSLASH",{0.04,Animate2D::Style::OneShot});

	CreateStillAnimation(game->GFX_EnergyBolt,{24,24},"ENERGY_BOLT");

	CreateHorizontalAnimationSequence(game->GFX_EnergyParticle,3,{3,3},"ENERGY_PARTICLE");

	CreateHorizontalAnimationSequence(game->GFX_Splash_Effect,5,{24,24},"SPLASH_EFFECT",{0.05});
	
	CreateStillAnimation(game->GFX_BulletCircle,{3,3},"DOT_PARTICLE");

	CreateHorizontalAnimationSequence(game->GFX_LightningBolt,5,{24,24},"LIGHTNING_BOLT",{0.03,Animate2D::Style::PingPong});

	CreateStillAnimation(game->GFX_LightningBoltParticle1,{5,5},"LIGHTNING_BOLT_PARTICLE1");
	CreateStillAnimation(game->GFX_LightningBoltParticle2,{5,5},"LIGHTNING_BOLT_PARTICLE2");
	CreateStillAnimation(game->GFX_LightningBoltParticle3,{5,5},"LIGHTNING_BOLT_PARTICLE3");
	CreateStillAnimation(game->GFX_LightningBoltParticle4,{5,5},"LIGHTNING_BOLT_PARTICLE4");

	CreateStillAnimation(game->GFX_ChainLightning,{1,9},"CHAIN_LIGHTNING");

	CreateHorizontalAnimationSequence(game->GFX_LightningSplash,5,{24,24},"LIGHTNING_SPLASH");

	CreateStillAnimation(game->GFX_Meteor,{192,192},"METEOR");

	for(int i=0;i<5;i++){
		Animate2D::FrameSequence firering;
		firering.AddFrame({&game->GFX_LightningSplash,{{i*24,0},{24,24}}});
		ANIMATION_DATA["FIRE_RING"+std::to_string(i+1)]=firering;
	}
	CreateStillAnimation(game->GFX_Arrow,{24,24},"ARROW");
	CreateStillAnimation(game->GFX_ChargedArrow,{48,48},"CHARGED_ARROW");
	CreateStillAnimation(game->GFX_Laser,{5,1},"LASER");
	CreateStillAnimation(game->GFX_RangeIndicator,{24,24},"RANGE_INDICATOR");
}

void sig::Animation::SetupPlayerAnimations(){
	int counter=0;
	while("Player"_A.HasProperty("PLAYER_ANIMATION["+std::to_string(counter)+"]")){
		game->GetPlayer()->AddAnimation(DATA["Player"]["PLAYER_ANIMATION["+std::to_string(counter)+"]"].GetString()+"_N");
		game->GetPlayer()->AddAnimation(DATA["Player"]["PLAYER_ANIMATION["+std::to_string(counter)+"]"].GetString()+"_E");
		game->GetPlayer()->AddAnimation(DATA["Player"]["PLAYER_ANIMATION["+std::to_string(counter)+"]"].GetString()+"_S");
		game->GetPlayer()->AddAnimation(DATA["Player"]["PLAYER_ANIMATION["+std::to_string(counter)+"]"].GetString()+"_W");
		counter++;
	}

	ANIMATION_DATA.SetInitialized();
}