/*
	Asteroids
    Copyright (C) 2006  Darragh Coy.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/*##############################################################################

Module name: Game.cpp
Purpose:     Does the game loop and stores game data.

##############################################################################*/

#include "Game.h"

/*******************************************************************************
Private module prototypes: Not for outside use!
*******************************************************************************/

   void Game_FunctionKeyCheck();   // Check for special game function key presses

/*******************************************************************************
Variables
*******************************************************************************/

   // Main game data

   GameData_t gamedata;

   // High score and name of person who got that highscore

   unsigned int highScore = 0;
   char         highScoreName[PLAYER_NAME_LENGHT+1] = {0};

   // Name of current player

   char playerName[PLAYER_NAME_LENGHT+1] = {0};

   // Name of the last player

   char lastPlayerName[PLAYER_NAME_LENGHT+1] = {0};

   // Is the game paused ?

   bool gamePaused = false;

   // Is the player entering their name at the moment ?

   bool enteringName = false;

   // Draw performance info ?

   bool showPerformanceInfo = false;

   // Game performance logging: how many clocks to render and go game loop ?

   int clocks_draw = 0;
   int clocks_game = 0;

/*******************************************************************************

Name:       Game_Init
Purpose:    Initialises the game
Parameters: None
Returns:    None

*******************************************************************************/

void Game_Init ( void )
{
    // Load last high score from file if it it hasn't been loaded already
    // If the high score is 0 then more than likely it hasnt been loaded

    if ( highScore == 0 ) Saves_LoadScore();

    // Setup player

    gamedata.player.orientation = 90;
    gamedata.player.velocity.x  = 0;
    gamedata.player.velocity.y  = 0;
    gamedata.player.score       = 0;

    // Initialise various things

    Timer_Init();                 // Initialise the timer
    Player_Init   (&gamedata);    // Initialise the player
    Bullet_Init   (&gamedata);    // Initialise bullets
    Asteroid_Init (&gamedata);    // Initialise asteroids
    Particle_Init();              // Initialise particles
    Stars_Init();                 // Intialise stars

    // Unpause timer to discount initialisation time:

    Timer_Unpause();
}

/*******************************************************************************

Name:       Game_End
Purpose:    Finishes up the game by recording the current high score
Parameters: None
Returns:    None

*******************************************************************************/

void Game_End ( void )
{
    // Save the current high score

    Saves_SaveScore();

    // Save current user data: if no name entered then nothing will happen

    Saves_SaveUser(&gamedata);

    // If user name not blank then ask the user do they want to save on exit

    if ( playerName[0] != '\0' )
    {
       // Ask the user:

       bool save = GLWin_Prompt
        (
            "Do you want to save the game before finishing ?",
            "Save game?"
        );

       // If save confirmed then save:

       if ( save ) Saves_SaveGame(&gamedata);
    }

}


/*******************************************************************************

Name:       Game_DoGameLoop
Purpose:    Does one frame of the game loop, everything from processing the game
            state till drawing.
Parameters: None
Returns:    None

*******************************************************************************/

void Game_DoGameLoop ( void )
{
     // Update the game timer

     Timer_Update();

     // Two varibales to hold clock times

     LARGE_INTEGER clockStart;
     LARGE_INTEGER clockEnd;

     // Check for special game function keys

     Game_FunctionKeyCheck();

     // Get current clock count

     QueryPerformanceCounter(&clockStart);

     // Process game state if game not paused

     if ( ( ! gamePaused ) && ( ! enteringName ) )
     {


         Particle_Move ();             // Move all particles
         Asteroid_Move (&gamedata);    // Move all asteroids

         // Only move player if not dead:

         if ( gamedata.player.playerAlive )
         {
            Player_Move(&gamedata);
         }

         Bullet_Move   (&gamedata);    // Move all bullets
     }

     // If player entering name then see if there is a key waiting to be input

     if ( enteringName )
     {
        Player_EnterName(&gamedata);

        // Keep unpausing the timer to discount time spent entering name:

        Timer_Unpause();
     }

     // Get current clock count

     QueryPerformanceCounter(&clockEnd);

     // Save difference as time taken to do game loop

     clocks_game = clockEnd.LowPart - clockStart.LowPart;

     // Get current clock count

     QueryPerformanceCounter(&clockStart);

     // Redraw the screen

     GLDraw_Redraw(&gamedata);

     // Get current clock count

     QueryPerformanceCounter(&clockEnd);

     // Save difference as time taken to draw game

     clocks_draw = clockEnd.LowPart - clockStart.LowPart;

}

/*******************************************************************************

Name:       Game_FunctionKeyCheck
Purpose:    Checks if any special game function keys such as pause and save
            are pressed and takes the appropriate action.
Parameters: None
Returns:    None

*******************************************************************************/

void Game_FunctionKeyCheck ( void )
{
    /***************************************************************************
    Check first if entering name: in this case do not do anything until name
    entering has finished:
    ***************************************************************************/

    if ( enteringName ) return;

    /***************************************************************************
    Check for Information Key (F1)
    ***************************************************************************/

    if ( GLWin_Keydown[VK_F1] )
    {
       // Set F1 Key as not being pressed

       GLWin_Keydown[VK_F1] = false;

       // Display information message:

       GLWin_Message
       (
         "Shoot asteroids to increase your score.    \n"
         "Try to beat the top score for kudos!       \n"
         "                                           \n"
         "Game controls are as follows:              \n"
         "                                           \n"
         "SPACE : Shoot                              \n"
         "UP    : Foward thrust                      \n"
         "LEFT  : Turn left                          \n"
         "RIGHT : Turn right                         \n"
         "N     : Enter player name / Login          \n"
         "S     : Display high scores for all users  \n"
         "P     : Pause game                         \n"
         "R     : Restart game                       \n"
         "F6    : Save game                          \n"
         "F9    : Load game                          \n"
         "F12   : Enable / Disable performance stats \n" ,
         "Instructions"
       );

        // Unpause the timer to discount time passed while dialog was showing

        Timer_Unpause();
    }

    /***************************************************************************
    Check for Restart key 'R'
    ***************************************************************************/

    if ( GLWin_Keydown['R'] )
    {
        // Save players own best score: data will erased on reinitialisation of game

        unsigned int playerBest = gamedata.player.scoreHighest;

        // Restart the game

        Game_Init();

        // Reset the players best score

        gamedata.player.scoreHighest = playerBest;

        // Set restart key to not pressed

        GLWin_Keydown['R'] = false;
    }

    /***************************************************************************
    Check if Performance info key pressed (F12)
    ***************************************************************************/

    if ( GLWin_Keydown[VK_F12] )
    {
       // Set F12 Key as not being pressed

       GLWin_Keydown[VK_F12] = false;

       // Change state of show performance info boolean

       showPerformanceInfo = ! showPerformanceInfo;
    }

    /***************************************************************************
    Check for Save or load key:
    ***************************************************************************/

    if ( GLWin_Keydown[VK_F6] )
    {
        // Set saved key as not pressed. Set load key as not pressed (in case it is)

        GLWin_Keydown[VK_F6] = false;
        GLWin_Keydown[VK_F9] = false;

        // Save game

        Saves_SaveGame(&gamedata);

        // Unpause timer to discount time passed when saving

        Timer_Unpause();
    }
    else if ( GLWin_Keydown[VK_F9] )
    {
        // Set load key as not pressed

        GLWin_Keydown[VK_F9] = false;

        // laod game

        Saves_LoadGame(&gamedata);

        // Unpause timer to discount time passed when loading

        Timer_Unpause();
    }

    /***************************************************************************
    Check for pause key:
    ***************************************************************************/

    // If pause key pressed then change pause state

    if ( GLWin_Keydown['P'] )
    {
        // Pause key down: change pause state

        gamePaused = ! gamePaused;

        // Set paused key as not pressed

        GLWin_Keydown['P'] = false;

        // If unpausing then discount the time passed while paused:

        Timer_Unpause();
    }

    /***************************************************************************
    Check for show scores key
    ***************************************************************************/

    // If show scores key pressed then change pause state

    if ( GLWin_Keydown['S'] )
    {
        // Set S key as not pressed

        GLWin_Keydown['S'] = false;

        // Save current user data high score so it is included in the html file

        Saves_SaveUser(&gamedata);

        // Show scores to the user

        ShowScores_Show();

        // Unpause timer to discount time spent saving to html file

        Timer_Unpause();
    }


    /***************************************************************************
    Check for enter name key:
    ***************************************************************************/

    // If pause key pressed then change pause state

    if ( GLWin_Keydown['N'] )
    {
        // If not entering name already and exiting then save current user high
        // score in case of a user switch

        if ( ! enteringName ) Saves_SaveUser(&gamedata);

        // Change entering name state

        enteringName = ! enteringName;

        // Set n key as not pressed

        GLWin_Keydown['N'] = false;

        // Set last key pressed as none or NULL

        GLWin_LastKey = 0;

        // Unpause the timer to discount time spent saving

        Timer_Unpause();
    }

}
