#include "Class.h"
#include "olcPixelGameEngine.h"
#include "DEFINES.h"
#include "Player.h"
#include "Effect.h"
#include "Crawler.h"
#include "BulletTypes.h"
#include "config.h"
#include "utils.h"

INCLUDE_MONSTER_LIST
INCLUDE_BULLET_LIST
INCLUDE_game

void Wizard::Initialize(){
    READFROMCONFIG(Wizard,WIZARD);
    Wizard::idle_n=WIZARD_IDLE_N;
    Wizard::idle_e=WIZARD_IDLE_E;
    Wizard::idle_s=WIZARD_IDLE_S;
    Wizard::idle_w=WIZARD_IDLE_W;
    Wizard::walk_n=WIZARD_WALK_N;
    Wizard::walk_e=WIZARD_WALK_E;
    Wizard::walk_s=WIZARD_WALK_S;
    Wizard::walk_w=WIZARD_WALK_W;
}

SETUP_CLASS(Wizard)

void Wizard::OnUpdate(float fElapsedTime){
    if(attack_cooldown_timer>0){
		idle_n=AnimationState::WIZARD_IDLE_ATTACK_N;
		idle_e=AnimationState::WIZARD_IDLE_ATTACK_E;
		idle_s=AnimationState::WIZARD_IDLE_ATTACK_S;
		idle_w=AnimationState::WIZARD_IDLE_ATTACK_W;
		walk_n=AnimationState::WIZARD_ATTACK_N;
		walk_e=AnimationState::WIZARD_ATTACK_E;
		walk_s=AnimationState::WIZARD_ATTACK_S;
		walk_w=AnimationState::WIZARD_ATTACK_W;
	} else {
		idle_n=AnimationState::WIZARD_IDLE_N;
		idle_e=AnimationState::WIZARD_IDLE_E;
		idle_s=AnimationState::WIZARD_IDLE_S;
		idle_w=AnimationState::WIZARD_IDLE_W;
		walk_n=AnimationState::WIZARD_WALK_N;
		walk_e=AnimationState::WIZARD_WALK_E;
		walk_s=AnimationState::WIZARD_WALK_S;
		walk_w=AnimationState::WIZARD_WALK_W;
	}
	if(GetState()==State::CASTING){
		switch(GetFacingDirection()){
			case UP:{
				UpdateAnimation(AnimationState::WIZARD_CAST_N,WIZARD|WITCH);
			}break;
			case DOWN:{
				UpdateAnimation(AnimationState::WIZARD_CAST_S,WIZARD|WITCH);
			}break;
			case LEFT:{
				UpdateAnimation(AnimationState::WIZARD_CAST_W,WIZARD|WITCH);
			}break;
			case RIGHT:{
				UpdateAnimation(AnimationState::WIZARD_CAST_E,WIZARD|WITCH);
			}break;
		}
	}
}

bool Wizard::AutoAttack(){
	attack_cooldown_timer=MAGIC_ATTACK_COOLDOWN;
	float angleToCursor=atan2(game->GetWorldMousePos().y-GetPos().y,game->GetWorldMousePos().x-GetPos().x);
	BULLET_LIST.push_back(std::make_unique<EnergyBolt>(EnergyBolt(GetPos(),{cos(angleToCursor)*"Wizard.Auto Attack.Speed"_F,sin(angleToCursor)*"Wizard.Auto Attack.Speed"_F},"Wizard.Auto Attack.Radius"_F/100*12,GetAttack(),upperLevel,true,WHITE)));
	return true;
}
void Wizard::InitializeClassAbilities(){
    #pragma region Wizard Right-click Ability (Teleport)
        Wizard::rightClickAbility.action=
            [](Player*p,vf2d pos={}){
                if(p->GetState()==State::CASTING)return false;
                float pointMouseDirection=atan2(game->GetWorldMousePos().y-p->GetPos().y,game->GetWorldMousePos().x-p->GetPos().x);
                vf2d pointTowardsMouse={cos(pointMouseDirection),sin(pointMouseDirection)};
                float dist=std::clamp(geom2d::line<float>{p->GetPos(),game->GetWorldMousePos()}.length(),0.f,"Wizard.Right Click Ability.TeleportRange"_F/100*24);
                if(dist<"Wizard.Right Click Ability.TilesMin"_I*12)return false;
                vf2d teleportPoint=p->GetPos()+pointTowardsMouse*dist;
                while(dist>0&&game->HasTileCollision(game->GetCurrentLevel(),teleportPoint)&&p->CanPathfindTo(p->GetPos(),teleportPoint,"Wizard.Right Click Ability.TilesMax"_I)){
                    dist-=24;
                    teleportPoint=p->GetPos()+pointTowardsMouse*dist;
                }
                if(dist>0&&p->CanPathfindTo(p->GetPos(),teleportPoint,"Wizard.Right Click Ability.TilesMax"_I)){
                    p->SetState(State::TELEPORT);
                    p->teleportAnimationTimer="Wizard.Right Click Ability.AnimationTime"_F;
                    p->teleportTarget=teleportPoint;
                    p->teleportStartPosition=p->GetPos();
                    p->iframe_time="Wizard.Right Click Ability.IframeTime"_F;
                    for(int i=0;i<"Wizard.Right Click Ability.ParticleCount"_I;i++){
                        game->AddEffect(
                            std::make_unique<Effect>(
                                p->GetPos()+
                                vf2d{(util::random("Wizard.Right Click Ability.ParticleRange"_F/100*2)-
                                    "Wizard.Right Click Ability.ParticleRange"_F/100)*12
                                ,(util::random("Wizard.Right Click Ability.ParticleRange"_F/100*2)-
                                    "Wizard.Right Click Ability.ParticleRange"_F/100)*12},
                                util::random("Wizard.Right Click Ability.ParticleLifetimeMax"_F)+
                                "Wizard.Right Click Ability.ParticleLifetimeMin"_F,
                                AnimationState::DOT_PARTICLE,p->upperLevel,
                                "Wizard.Right Click Ability.ParticleSize"_F,
                                "Wizard.Right Click Ability.ParticleFadetime"_F,
                                vf2d{util::random("Wizard.Right Click Ability.ParticleSpeedMax"_F*2)+
                                "Wizard.Right Click Ability.ParticleSpeedMin"_F,
                                util::random("Wizard.Right Click Ability.ParticleSpeedMax"_F*2)+
                                "Wizard.Right Click Ability.ParticleSpeedMin"_F},
                                "Wizard.Right Click Ability.ParticleColor"_Pixel));
                    }
                    return true;
                } else {
                    p->notificationDisplay={"Cannot Teleport to that location!",0.5};
                    return false;
                }
            };
    #pragma endregion
    #pragma region Wizard Ability 1 (Fire Bolt)
        Wizard::ability1.action=
            [](Player*p,vf2d pos={}){
                float angleToCursor=atan2(game->GetWorldMousePos().y-p->GetPos().y,game->GetWorldMousePos().x-p->GetPos().x);
                BULLET_LIST.push_back(std::make_unique<FireBolt>(FireBolt(p->GetPos(),{cos(angleToCursor)*275,sin(angleToCursor)*275},12,p->GetAttack(),p->upperLevel,true,{240,120,60})));
                return true;
            };
    #pragma endregion
    #pragma region Wizard Ability 2 (Lightning Bolt)
        Wizard::ability2.action=
            [](Player*p,vf2d pos={}){
                float angleToCursor=atan2(game->GetWorldMousePos().y-p->GetPos().y,game->GetWorldMousePos().x-p->GetPos().x);
                BULLET_LIST.push_back(std::make_unique<LightningBolt>(LightningBolt(p->GetPos(),{cos(angleToCursor)*230,sin(angleToCursor)*230},12,p->GetAttack()*4,p->upperLevel,true,WHITE)));
                return true;
            };
    #pragma endregion
    #pragma region Wizard Ability 3 (Meteor)
        Wizard::ability3.action=
            [](Player*p,vf2d pos={}){
                p->CastSpell(Wizard::ability3);
                game->AddEffect(std::make_unique<Meteor>(pos,3,AnimationState::METEOR,p->OnUpperLevel(),vf2d{1,1},2));
                return true;
            };
    #pragma endregion
}