#include "Player.h"
#include "sprig.h"
#include "extraMath.h"
#include <cmath>


#define PLAYER_SPEED 800
#define CPU_SPEED 700
#define PLAYER_MAXSPEED 200
#define CPU_MAXSPEED 200

Player::Player()
{
    boat = new Boat;
    //boat->team = 0;
    boat->hpMax = 10;
    boat->hp = boat->hpMax;
    boat->maxVel = PLAYER_MAXSPEED;
    
    b_up = controls.addButton(Button(SDLK_UP));
    b_down = controls.addButton(Button(SDLK_DOWN));
    b_left = controls.addButton(Button(SDLK_LEFT));
    b_right = controls.addButton(Button(SDLK_RIGHT));
    
    b_up2 = controls.addButton(Button(SDLK_w));
    b_down2 = controls.addButton(Button(SDLK_s));
    b_left2 = controls.addButton(Button(SDLK_a));
    b_right2 = controls.addButton(Button(SDLK_d));
    
    b_fire = controls.addButton(Button(SDLK_SPACE));
    b_fire2 = controls.addButton(Button(Button::MOUSEBUTTON, 0));  // Left mouse button
    
    b_anchor = controls.addButton(Button(SDLK_LSHIFT));
    b_anchor2 = controls.addButton(Button(Button::MOUSEBUTTON, 2));  // Right mouse button
}

Player::~Player()
{
    delete boat;
}


void Player::update(GameState* state)
{
    if(controls.checkHold(b_up) || controls.checkHold(b_up2))
    {
        boat->vely -= PLAYER_SPEED*state->dt;
    }
    if(controls.checkHold(b_down) || controls.checkHold(b_down2))
    {
        boat->vely += PLAYER_SPEED*state->dt;
    }
    if(controls.checkHold(b_left) || controls.checkHold(b_left2))
    {
        boat->velx -= PLAYER_SPEED*state->dt;
    }
    if(controls.checkHold(b_right) || controls.checkHold(b_right2))
    {
        boat->velx += PLAYER_SPEED*state->dt;
    }
    if(controls.checkHold(b_fire) || controls.checkHold(b_fire2))
    {
        boat->fire(state);
    }
    
    boat->update(state->dt);
        
    // Restrict to level boundaries
    if(boat->x < state->minX)
    {
        boat->x = state->minX;
        boat->velx = -boat->velx/2;
    }
    else if(boat->x > state->maxX)
    {
        boat->x = state->maxX;
        boat->velx = -boat->velx/2;
    }

    if(boat->y < state->minY)
    {
        boat->y = state->minY;
        boat->vely = -boat->vely/2;
    }
    else if(boat->y > state->maxY)
    {
        boat->y = state->maxY;
        boat->vely = -boat->vely/2;
    }
}


bool Player::checkInput(SDL_Event& event, GameState* state)
{
    unsigned int button = controls.checkInput(event);
    
    if(button == b_fire || button == b_fire2)
    {
        boat->fire(state);
        return true;
    }
    if(button == b_anchor || button == b_anchor2 || (event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_RIGHT))
    {
        if(boat->anchorTimer < 0)
        {
            boat->tossAnchor(state);
        }
        return true;
    }
    return false;
}



CPU::CPU()
{
    boat = new Boat;
    //boat->team = 1;
    boat->shotTimerMax = 0.8f;
    boat->maxVel = CPU_MAXSPEED;
}

CPU::~CPU()
{
    delete boat;
}


void CPU::chase(GameState* state, float x, float y)
{
    if(y < boat->y)
    {
        boat->vely -= CPU_SPEED*state->dt;
    }
    else if(y > boat->y)
    {
        boat->vely += CPU_SPEED*state->dt;
    }
    if(x < boat->x)
    {
        boat->velx -= CPU_SPEED*state->dt;
    }
    else if(x > boat->x)
    {
        boat->velx += CPU_SPEED*state->dt;
    }
}

void CPU::circle(GameState* state, Boat* target)
{
    float dir = atan2(target->y - boat->y, target->x - boat->x);
    dir += PI_8;
    
    boat->velx += cos(dir)*CPU_SPEED/4*state->dt;
    boat->vely += sin(dir)*CPU_SPEED/4*state->dt;
}

void CPU::attack(GameState* state, Boat* target)
{
    boat->target.x = target->x + target->velx*0.5f; // Guessing ahead 1/2 second
    boat->target.y = target->y + target->vely*0.5f;
    
    boat->fire(state);
}

void CPU::attack(GameState* state, Island* target)
{
    boat->target.x = target->x;
    boat->target.y = target->y;
    
    boat->fire(state);
}



void CPU::update(GameState* state)
{
    if(boat->hp > 0)
    {
        // Find a new target
        Boat* target = NULL;
        float bdist = 99999999;
        Chest* c = NULL;
        float cdist = 99999999;
        Map* m = NULL;
        float mdist = 99999999;
        Island* island = NULL;
        float idist = 99999999;
        
        // Find the nearest enemy BOAT
        for(vector<Boat*>::iterator e = state->boats.begin(); e != state->boats.end(); e++)
        {
            // Don't care about my own team
            if((*e)->team == boat->team)
                continue;
            
            if(target == NULL)
            {
                target = *e;
                bdist = dist2(target, boat);
            }
            else
            {
                float newdist = dist2(*e, boat); // Har har...
                if(bdist > newdist)
                {
                    target = *e;
                    bdist = newdist;
                }
            }
        }
        
        if(boat->maps.size() > 0)
        {
            // We have a map, so go for the gold! CHEST
            c = boat->maps.front()->target;
            if(c != NULL)
                cdist = dist2(c, boat);
        }
        else
        {
            // Look for a floating MAP
            for(list<Map*>::iterator e = state->floatingMaps.begin(); e != state->floatingMaps.end(); e++)
            {
                if(m == NULL)
                {
                    m = *e;
                    mdist = dist2(m, boat);
                }
                else
                {
                    float newdist = dist2(*e, boat); // Har har...
                    if(mdist > newdist)
                    {
                        m = *e;
                        mdist = newdist;
                    }
                }
            }
            
            // No map, so try to find one on an ISLAND
            for(vector<Island*>::iterator e = state->islands.begin(); e != state->islands.end(); e++)
            {
                if((*e)->chest != NULL)
                {
                    island = *e;
                    idist = dist2(island, boat);
                    break;
                }
            }
        }
        
        if(target == NULL && m == NULL && c == NULL && island == NULL)
        {
            return;
        }
        
        if(target != NULL && bdist < cdist && bdist < idist && bdist < mdist)
        {
            // Go for the BOAT
            if(bdist > 600*600)
                chase(state, target->x, target->y);
            else
            {
                circle(state, target);
                attack(state, target);
            }
        }
        else if(c != NULL)
        {
            // Go for the CHEST
            if(cdist > 50*50)
                chase(state, c->x, c->y);
            else
            {
                boat->tossAnchor(state);
            }
        }
        else if(m != NULL && mdist < idist)
        {
            // Go for the MAP
            chase(state, m->x, m->y);
        }
        else if(island != NULL)
        {
            // Go for the ISLAND
            if(idist > 600*600 || island->chest->isOpen)
                chase(state, island->x, island->y);
            else
            {
                attack(state, island);
            }
        }
    }
    
    boat->update(state->dt);
    
    
        
    // Restrict to level boundaries
    if(boat->x < state->minX)
    {
        boat->x = state->minX;
        boat->velx = -boat->velx/2;
    }
    else if(boat->x > state->maxX)
    {
        boat->x = state->maxX;
        boat->velx = -boat->velx/2;
    }

    if(boat->y < state->minY)
    {
        boat->y = state->minY;
        boat->vely = -boat->vely/2;
    }
    else if(boat->y > state->maxY)
    {
        boat->y = state->maxY;
        boat->vely = -boat->vely/2;
    }
}
