#include "GameLogic.h"
#include "Main.h"
#include "EntPlayer.h"
#include "EntLightBeam.h"
#include "EntObstacle.h"
#include "EntSwimmer.h"
#include "EntSplash.h"
#include "EntUpgrade.h"



void GetRandomPosition(CL_Vector2 &v)
{
   
    int tries = 0;
again:

    tries++;
    float dist = 100+Random(300);
    float angle = FRandomRange(0, float(PI*2));
    
    v.x = cos(angle)*dist;
    v.y = sin(angle)*dist;
    
    //offset to the center
    
    v.x += GetScreenX/2;
    v.y += GetScreenY/2;

    if (tries > 5000) return; //emergency protection against a crash

    if (v.y < 40) goto again; //don't screw with the interface area
    if (v.y > GetScreenY-10) goto again;


    //if too close to the player, try again
    assert(GetGameLogic->GetPlayer() && "Init the player first!");

    CL_Vector2 offset = GetGameLogic->GetPlayer()->m_vPosition-v;
    if (abs(offset.length()) < 15) goto again; //too close to the player or another obstacle

    if (GetMyEntityMgr->TouchedEntity(C_TYPE_ANY, v, 15)) goto again;
 
}


GameLogic::GameLogic()
{
    ResetGame();
    m_slotKeyDown = CL_Keyboard::sig_key_down().connect(this, &GameLogic::OnKeyDown);
  
    for (int i=0; i < C_SOUND_COUNT; i++)
    {
        m_sounds[i] = NULL;
    }

    m_sounds[C_SOUND_COAST_GUARD] = new CL_SoundBuffer("media\\intro.wav");
    m_sounds[C_SOUND_LEVEL_START] = new CL_SoundBuffer("media\\level_start.wav");
    m_sounds[C_SOUND_ROCK_PLACED] = new CL_SoundBuffer("media\\rock_placed.wav");

    m_sounds[C_SOUND_RESCUE] = new CL_SoundBuffer("media\\rescue_blip.wav");
 
    m_sounds[C_SOUND_GUY1_HELP] = new CL_SoundBuffer("media\\man1_help.wav");
    m_sounds[C_SOUND_GUY2_HELP] = new CL_SoundBuffer("media\\man2_help.wav");
    m_sounds[C_SOUND_GUY3_HELP] = new CL_SoundBuffer("media\\man3_help.wav");
    m_sounds[C_SOUND_GUY4_HELP] = new CL_SoundBuffer("media\\spacetaxi_help.wav");

    m_sounds[C_SOUND_GUY1_THANKS] = new CL_SoundBuffer("media\\man1_thanks.wav");
    m_sounds[C_SOUND_GUY2_THANKS] = new CL_SoundBuffer("media\\man2_thanks.wav");
    m_sounds[C_SOUND_GUY3_THANKS] = new CL_SoundBuffer("media\\man3_thanks.wav");
    m_sounds[C_SOUND_GUY4_THANKS] = new CL_SoundBuffer("media\\spacetaxi_thanks.wav");

    m_sounds[C_SOUND_SWIMMER_DIE] = new CL_SoundBuffer("media\\swimmer_die.wav");
    m_sounds[C_SOUND_COOLCAT] = new CL_SoundBuffer("media\\coolcat.wav");
    m_sounds[C_SOUND_CRASH] = new CL_SoundBuffer("media\\crash.wav");
    m_sounds[C_SOUND_RESCUE_BLIP] = new CL_SoundBuffer("media\\rescue_blip.wav");
    
    m_myEntityManager.Init();
    m_myEntityManager.Add(new EntSplash);

}

void GameLogic::ResetGame()
{
    m_rescuesNeededForUpgrade = 6;
    m_rescues = 0;
    m_drownTimerMax = 10000;
    m_lightHouseSpeed = 0.4f;
    m_level = 1;
    m_beamScale = 10;
    m_bSuspended = false;
    m_pPlayer = NULL;
    m_bJustStarted = true;

    for (int i=0; i < C_UPGRADE_TYPES; i++)
        m_upgrade[i] = 0;
}

void GameLogic::OnRescued()
{
    m_rescues++;
    if (m_rescues >= m_rescuesNeededForUpgrade)
    {
       m_rescuesNeededForUpgrade += 1;
       if (m_rescuesNeededForUpgrade > 14)
       {
           m_rescuesNeededForUpgrade = 14;
       }
       if (Random(6) == 0)
        {
            //my hamumu impression!
            GetMessageDispatcher()->SendMsg(C_MESSAGE_SOUND, 0, NULL, C_SOUND_COOLCAT);

        }   else
        {
            GetMessageDispatcher()->SendMsg(C_MESSAGE_SOUND, 0, NULL, C_SOUND_COAST_GUARD);
        }
      GetMessageDispatcher()->SendText("US Coast Guard!!!", 0);
       m_rescues = 0;
        m_myEntityManager.Add(new EntUpgrade);
    }

}

GameLogic::~GameLogic()
{
    m_messageDispatcher.ClearAllMessages();
    Kill();
    for (int i=0; i < C_SOUND_COUNT; i++)
    {
        SAFE_DELETE(m_sounds[i]);
    }

}

bool GameLogic::Init()
{
   m_textTimer = 0;
   
   m_rocksPlacedSoFar = 0;   
   m_rockSpawnMS = 400;

   switch (m_level)
   {
   case 1:

       m_rocks = 5;
       m_guysToSpawn = 6;
       m_spawnSpeed = 3000;
       break;
  
   case 2:
       
       m_rocks = 7;
       m_guysToSpawn = 6;
       m_spawnSpeed = 2000;
       break;
   
   case 3:
       
       m_rocks = 8;
       m_guysToSpawn = 6;
       m_spawnSpeed = 1600;
       break;

   case 4:
       
       m_rocks = 10;
       m_guysToSpawn = 6;
       m_spawnSpeed = 1300;
       break;

   case 5:
       
       m_rocks = 12;
       m_guysToSpawn = 6;
       m_spawnSpeed = 1000;
       break;
       
   case 6:
       
       m_rocks = 80;
       m_guysToSpawn = 6;
       m_spawnSpeed = 40;
       m_rockSpawnMS = 50;
       GetMessageDispatcher()->SendText("Just kidding.  You already won.  Good job!", 6000);
     break;

   default:

       ;
       assert(!"Eh!");

   }

     
    char st[256];
    sprintf(st, "Day %d", m_level);

    GetMessageDispatcher()->SendText(st, 1000);
    GetMessageDispatcher()->SendMsg(C_MESSAGE_SOUND, 1000, NULL, C_SOUND_LEVEL_START);
    GetMessageDispatcher()->SendText("Low tide...", 3000);
    GetMessageDispatcher()->SendMsg(C_MESSAGE_ADD_ROCK, 4000);

   return true;
}

void GameLogic::AddRock()
{
    m_rocksPlacedSoFar++;
   
    if (m_rocksPlacedSoFar <= m_rocks)
    {
        //keep placin' more!
        m_myEntityManager.Add(new EntObstacle);
        GetMessageDispatcher()->SendMsg(C_MESSAGE_ADD_ROCK, m_rockSpawnMS);
        GetMessageDispatcher()->SendMsg(C_MESSAGE_SOUND, 50, NULL, C_SOUND_ROCK_PLACED);
      } else
    {
        //start the game
         GetMessageDispatcher()->SendMsg(C_MESSAGE_ADD_PERSON, 2000, NULL, 0);
         GetMessageDispatcher()->SendMsg(C_MESSAGE_START_NIGHT, 20000, NULL, 0);
         GetMessageDispatcher()->SendText("The sun is setting.", 17000);
         GetMessageDispatcher()->SendMsg(C_MESSAGE_START_DAY, 53000, NULL, 0);
      }

}


void GameLogic::OnMessage(Message &msg)
{
    switch(msg.msg)
    {
    case C_MESSAGE_SOUND:
        Play(msg.parm1);

        break;
    case C_MESSAGE_TEXT:
        {
            m_textMessage = msg.text;
        int ms = msg.text.length()*100;
        if (ms < 2000) ms = 2000;
        m_textTimer = CL_System::get_time() + ms;
        break;
        }
    case C_MESSAGE_ADD_ROCK:
        AddRock();
        break;
    case C_MESSAGE_ADD_PERSON:
       AddPerson();
       break;

    case C_MESSAGE_START_DAY:
        m_level++;
        m_messageDispatcher.KillMessageType(C_MESSAGE_ADD_PERSON);
        Init();
        break;

    case C_MESSAGE_INIT_NEW_GAME:

        m_myEntityManager.Add(m_pPlayer = new EntPlayer);
        m_myEntityManager.Add(new EntLightBeam);

        Init();
        break;

    case C_MESSAGE_GAME_OVER:
        
        m_myEntityManager.Init(); //kill everything
        ResetGame();
        m_messageDispatcher.ClearAllMessages();
        m_myEntityManager.Add(new EntSplash);
        

       break;
   }
}

void GameLogic::OnKeyDown(const CL_InputEvent &key)
{
         switch (key.id)
        {
            
        case  CL_KEY_F11:

            break;
        }
    
}

void GameLogic::AddPerson()
{
    m_myEntityManager.Add(new EntSwimmer);
 
    GetMessageDispatcher()->SendMsg(C_MESSAGE_ADD_PERSON, (m_spawnSpeed/2)+Random(m_spawnSpeed), NULL, 0);
 
}


void GameLogic::RebuildBuffers()
{
    //note, currently, this can get called before Init() is called!
 //   GetApp()->GetBackgroundCanvas()->get_gc()->clear(CL_Color(0,255,255));
}

void GameLogic::Kill()
{

}

void GameLogic::Update(float step)
{
    m_messageDispatcher.Update();  
    m_myEntityManager.Update(step);
}

void GameLogic::DrawGUI()
{
    char st[256];

    sprintf(st, "Day: %d", m_level);
    GetApp()->GetFont(C_FONT_BLACK)->draw(10,1, st);

    sprintf(st, "Boat Hull: %%%d", m_pPlayer->GetHealthPercent());
    GetApp()->GetFont(C_FONT_BLACK)->draw(130,1, st);

    sprintf(st, "Next Upgrade: %d more rescues", m_rescuesNeededForUpgrade - m_rescues);
    GetApp()->GetFont(C_FONT_BLACK)->draw(400,1, st);

    if (m_textTimer > CL_System::get_time())
    {
        GetApp()->GetFont(C_FONT_YELLOW)->draw(GetScreenX/2, 250, m_textMessage);
    }

}

void GameLogic::Render()
{

    // CL_Display::clear(CL_Color(0,0,255));
    GetApp()->GetBackground()->draw(0,0);
    m_myEntityManager.Render();    
    
    if (m_pPlayer)
    {
       DrawGUI();
    }

}

