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

INCLUDE_MONSTER_LIST
INCLUDE_BULLET_LIST
INCLUDE_game

std::string Warrior::name="Warrior";
Class Warrior::cl=WARRIOR;
Ability Warrior::rightClickAbility={"Block",15,0,VERY_DARK_BLUE,DARK_BLUE};
Ability Warrior::ability1={"Battlecry",12,40};
Ability Warrior::ability2={"Ground Slam",15,50};
Ability Warrior::ability3={"Sonic Slash",40,60};
Ability Warrior::ability4={"???",0,0};
AnimationState Warrior::idle_n=WARRIOR_IDLE_N;
AnimationState Warrior::idle_e=WARRIOR_IDLE_E;
AnimationState Warrior::idle_s=WARRIOR_IDLE_S;
AnimationState Warrior::idle_w=WARRIOR_IDLE_W;
AnimationState Warrior::walk_n=WARRIOR_WALK_N;
AnimationState Warrior::walk_e=WARRIOR_WALK_E;
AnimationState Warrior::walk_s=WARRIOR_WALK_S;
AnimationState 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()
                &&m.OnUpperLevel()==OnUpperLevel()
                &&geom2d::overlaps(geom2d::circle<float>(GetPos()-vf2d{GetSizeMult()*12,GetSizeMult()*12},attack_range*GetSizeMult()*12),geom2d::circle<float>(m.GetPos()-vf2d{m.GetSizeMult()*12,m.GetSizeMult()*12},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())){
            attack_cooldown_timer=ATTACK_COOLDOWN;
            swordSwingTimer=0.2;
            SetState(State::SWING_SWORD);
            switch(facingDirection){
                case DOWN:{
                    UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_S,WARRIOR|THIEF);
                }break;
                case RIGHT:{
                    UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_E,WARRIOR|THIEF);
                }break;
                case LEFT:{
                    UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_W,WARRIOR|THIEF);
                }break;
                case UP:{
                    UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_N,WARRIOR|THIEF);
                }break;
            }
        }
    }
    return true;
}
void Warrior::InitializeClassAbilities(){
    #pragma region Warrior Right-click Ability (Block)
        Warrior::rightClickAbility.action=
            [&](){
                if(GetState()==State::NORMAL){
                    rightClickAbility.cooldown=rightClickAbility.COOLDOWN_TIME;
                    SetState(State::BLOCK);
                    AddBuff(BuffType::SLOWDOWN,3,0.3);
                    return true;
                }
                return false;
            };
    #pragma endregion
    #pragma region Warrior Ability 1 (Battlecry)
        Warrior::ability1.action=
            [&](){
                game->AddEffect(std::make_unique<Effect>(GetPos(),0.1,AnimationState::BATTLECRY_EFFECT,upperLevel,1,0.3));
                AddBuff(BuffType::ATTACK_UP,10,0.1);
                AddBuff(BuffType::DAMAGE_REDUCTION,10,0.1);
                for(Monster&m:MONSTER_LIST){
                    if(m.GetSizeMult()<=1&&geom2d::overlaps(geom2d::circle<float>(GetPos(),12*3.5),geom2d::circle<float>(m.GetPos(),m.GetSizeMult()*12))){
                        m.AddBuff(BuffType::SLOWDOWN,5,0.3);
                    }
                }
                return true;
            };
    #pragma endregion
    #pragma region Warrior Ability 2 (Ground Slam)
        Warrior::ability2.action=
            [&](){
                Spin(GROUND_SLAM_SPIN_TIME,14*PI);
                iframe_time=GROUND_SLAM_SPIN_TIME+0.1;
                return true;
            };
    #pragma endregion
    #pragma region Warrior Ability 3 (Sonic Slash)
        Warrior::ability3.action=
            [&](){
                SetState(State::SWING_SONIC_SWORD);
                AddBuff(BuffType::SLOWDOWN,0.5,1);
                vf2d bulletVel={};
                switch(GetFacingDirection()){
                    case UP:{
                        vel.y=70;
                        bulletVel.y=-400;
                        UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_N,WARRIOR);
                    }break;
                    case LEFT:{
                        vel.x=70;
                        bulletVel.x=-400;
                        UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_W,WARRIOR);
                    }break;
                    case RIGHT:{
                        vel.x=-70;
                        bulletVel.x=400;
                        UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_E,WARRIOR);
                    }break;
                    case DOWN:{
                        vel.y=-70;
                        bulletVel.y=400;
                        UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_S,WARRIOR);
                    }break;
                }
                BULLET_LIST.push_back(std::make_unique<Bullet>(GetPos(),bulletVel,30,GetAttack()*8,AnimationState::SONICSLASH,upperLevel,true,2.25,true,true,WHITE));
                game->SetupWorldShake(0.5);
                return true;
            };
    #pragma endregion
}