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

INCLUDE_MONSTER_LIST
INCLUDE_BULLET_LIST
INCLUDE_game

void Warrior::Initialize(){
    READFROMCONFIG(Warrior,WARRIOR);
    Warrior::idle_n="WARRIOR_IDLE_N";
    Warrior::idle_e="WARRIOR_IDLE_E";
    Warrior::idle_s="WARRIOR_IDLE_S";
    Warrior::idle_w="WARRIOR_IDLE_W";
    Warrior::walk_n="WARRIOR_WALK_N";
    Warrior::walk_e="WARRIOR_WALK_E";
    Warrior::walk_s="WARRIOR_WALK_S";
    Warrior::walk_w="WARRIOR_WALK_W";
}

SETUP_CLASS(Warrior)

void Warrior::OnUpdate(float fElapsedTime){

}

bool Warrior::AutoAttack(){
    if(GetState()!=State::SPIN){
        bool attack=false;
        Monster*closest=nullptr;
        float closest_dist=999999;
        for(Monster&m:MONSTER_LIST){
            if(m.IsAlive()
                &&geom2d::overlaps(geom2d::circle<float>(GetPos(),attack_range*GetSizeMult()*12),geom2d::circle<float>(m.GetPos(),m.GetSizeMult()*12))
                &&geom2d::line<float>(game->GetWorldMousePos(),m.GetPos()).length()<closest_dist){
                closest_dist=geom2d::line<float>(game->GetWorldMousePos(),m.GetPos()).length();
                closest=&m;
            }
        }
        if(closest!=nullptr&&closest->Hurt(GetAttack()*"Warrior.Auto Attack.DamageMult"_F,OnUpperLevel(),GetZ())){
            attack_cooldown_timer=ATTACK_COOLDOWN;
            swordSwingTimer="Warrior.Auto Attack.SwordSwingTime"_F;
            SetState(State::SWING_SWORD);
            switch(facingDirection){
                case DOWN:{
                    UpdateAnimation("WARRIOR_SWINGSWORD_S",WARRIOR|THIEF);
                }break;
                case RIGHT:{
                    UpdateAnimation("WARRIOR_SWINGSWORD_E",WARRIOR|THIEF);
                }break;
                case LEFT:{
                    UpdateAnimation("WARRIOR_SWINGSWORD_W",WARRIOR|THIEF);
                }break;
                case UP:{
                    UpdateAnimation("WARRIOR_SWINGSWORD_N",WARRIOR|THIEF);
                }break;
            }
        }
    }
    return true;
}
void Warrior::InitializeClassAbilities(){
    #pragma region Warrior Right-click Ability (Block)
        Warrior::rightClickAbility.action=
            [](Player*p,vf2d pos={}){
                if(p->GetState()==State::NORMAL){
                    rightClickAbility.cooldown=rightClickAbility.COOLDOWN_TIME;
                    p->SetState(State::BLOCK);
                    p->blockTimer="Warrior.Right Click Ability.Duration"_F;
                    p->AddBuff(BuffType::BLOCK_SLOWDOWN,"Warrior.Right Click Ability.Duration"_F,"Warrior.Right Click Ability.SlowAmt"_F);
                    return true;
                }
                return false;
            };
    #pragma endregion
    #pragma region Warrior Ability 1 (Battlecry)
        Warrior::ability1.action=
            [](Player*p,vf2d pos={}){
                game->AddEffect(std::make_unique<Effect>(p->GetPos(),"Warrior.Ability 1.EffectLifetime"_F,"battlecry_effect.png",p->upperLevel,"Warrior.Ability 1.Range"_F/350,"Warrior.Ability 1.EffectFadetime"_F));
                p->AddBuff(BuffType::ATTACK_UP,"Warrior.Ability 1.AttackUpDuration"_F,"Warrior.Ability 1.AttackIncrease"_F);
                p->AddBuff(BuffType::DAMAGE_REDUCTION,"Warrior.Ability 1.DamageReductionDuration"_F,"Warrior.Ability 1.DamageReduction"_F);
                for(Monster&m:MONSTER_LIST){
                    if(m.GetSizeMult()>="Warrior.Ability 1.AffectedSizeRange"_f[0]&&m.GetSizeMult()<="Warrior.Ability 1.AffectedSizeRange"_f[1]&&geom2d::overlaps(geom2d::circle<float>(p->GetPos(),12*"Warrior.Ability 1.Range"_I/100.f),geom2d::circle<float>(m.GetPos(),m.GetSizeMult()*12))){
                        m.AddBuff(BuffType::SLOWDOWN,"Warrior.Ability 1.SlowdownDuration"_F,"Warrior.Ability 1.SlowdownAmt"_F);
                    }
                }
                return true;
            };
    #pragma endregion
    #pragma region Warrior Ability 2 (Ground Slam)
        Warrior::ability2.action=
            [](Player*p,vf2d pos={}){
                p->Spin(GROUND_SLAM_SPIN_TIME,"Warrior.Ability 2.SpinSpd"_F*PI);
                p->iframe_time="Warrior.Ability 2.IframeTime"_F;
                return true;
            };
    #pragma endregion
    #pragma region Warrior Ability 3 (Sonic Slash)
        Warrior::ability3.action=
            [](Player*p,vf2d pos={}){
                p->SetState(State::SWING_SONIC_SWORD);
                p->AddBuff(BuffType::SLOWDOWN,"Warrior.Ability 3.StuckTime"_F,1);
                vf2d bulletVel={};
                switch(p->GetFacingDirection()){
                    case UP:{
                        p->vel.y="Warrior.Ability 3.AbilityPushback"_F;
                        bulletVel.y=-"Warrior.Ability 3.BulletSpd"_F;
                        p->UpdateAnimation("WARRIOR_SWINGSONICSWORD_N",WARRIOR);
                    }break;
                    case LEFT:{
                        p->vel.x="Warrior.Ability 3.AbilityPushback"_F;
                        bulletVel.x=-"Warrior.Ability 3.BulletSpd"_F;
                        p->UpdateAnimation("WARRIOR_SWINGSONICSWORD_W",WARRIOR);
                    }break;
                    case RIGHT:{
                        p->vel.x=-"Warrior.Ability 3.AbilityPushback"_F;
                        bulletVel.x="Warrior.Ability 3.BulletSpd"_F;
                        p->UpdateAnimation("WARRIOR_SWINGSONICSWORD_E",WARRIOR);
                    }break;
                    case DOWN:{
                        p->vel.y=-"Warrior.Ability 3.AbilityPushback"_F;
                        bulletVel.y="Warrior.Ability 3.BulletSpd"_F;
                        p->UpdateAnimation("WARRIOR_SWINGSONICSWORD_S",WARRIOR);
                    }break;
                }
                BULLET_LIST.push_back(std::make_unique<Bullet>(p->GetPos(),bulletVel,"Warrior.Ability 3.Radius"_F,p->GetAttack()*"Warrior.Ability 3.DamageMult"_F,"sonicslash.png",p->upperLevel,true,"Warrior.Ability 3.Lifetime"_F,true,true,WHITE,vf2d{"Warrior.Ability 3.Radius"_F/30,"Warrior.Ability 3.Radius"_F/30}));
                game->SetupWorldShake("Warrior.Ability 3.ShakeTime"_F);
                return true;
            };
    #pragma endregion
}