/*
	Rogue Trader.
	Copyright (c) 2007, Darragh Coy.
	All rights reserved.
	Original work(s), source code & author(s) details available at: http://www.darraghcoy.com

	Redistribution and use in source and binary forms, with or without modification, are permitted 
	provided that the following conditions are met:

		* 	Redistributions of source code must retain the above copyright notice, this list of 
			conditions and the following disclaimer.
		* 	Redistributions in binary form must reproduce the above copyright notice, this list of 
			conditions and the following disclaimer in the documentation.
		* 	Neither the name of the author nor the names of contributors may be used to endorse or 
			promote products derived from this software without specific prior written permission.
		* 	The use of any third party libraries, modules or data files provided with the source 
			form of the program must follow and respect the individual licensing terms of these 
			components. You do not have permission to modify or circumvent the licensing terms for 
			provided third party components unless the third party licenses specifically allow this. 
			If you do not agree to the terms of provided third party components then you do not have 
			permission to use them in your derived work(s).
		* 	The terms of this license do not apply to separate (but related) distributions if supplied 
			by the author(s), only to the contents of this source distribution, derived works, and the 
			binaries produced by either modified or unmodified versions of the source code. The terms 
			of this license do not also apply to any third party libraries or components provided with 
			the source distribution. Such third party elements are licensed under their own separate 
			agreements.

	THIS SOFTWARE IS PROVIDED BY DARRAGH COY ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
	BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
	ARE DISCLAIMED. IN NO EVENT SHALL DARRAGH COY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
	OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
	OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
	IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef GAME_H
#define GAME_H

//##############################################################################
// Game version
//##############################################################################

#define GAME_VERSION "1.04"

//##############################################################################
// C Includes
//##############################################################################

#include <Windows.h>
#include <gl/gl.h>
#include <cstring>
#include "MathLibrary.h"

//##############################################################################
// Forward references
//##############################################################################

class GLWindow;
class Timer;
class Camera;
class GameScene;
class GameObject;
class GameObjectHook;
class GameObject_SpaceStation;
class GameObject_Missile;
class GameObject_Ship;
class PlayerHuman;
class PlayerAI;
class GLFont;
class GLFontManager;
class GLTexture;
class GLTextureManager;
class GuiScreen_InGameMenu;
class Galaxy;
class SoundManager;
class SoundSystem;
class MusicSystem;

//##############################################################################
// C++ includes: can't forward reference these!
//##############################################################################

#include "GLWindowEventListener.h"
#include "StarSystem.h"

//##############################################################################
//##############################################################################
//##############################################################################
//##############################################################################
//
//
// Class Name:   Game
// Purpose:      Central game class. Runs the window and does a high level game
//               loop. The game class is also an event listener that can receive
//               events from the window.
//
//
//##############################################################################
//##############################################################################
//##############################################################################
//##############################################################################

class Game : public GLWindowEventListener
{

 public:

        //----------------------------------------------------------------------
        // Constants
        //----------------------------------------------------------------------

        static const float REPAIR_COST;					// repair cost per unit of damage
        static const float MISSILE_COST;				// cost for a missile
        static const float EMP_COST;					// cost for an emp bomb
        static const float REREFERNCE_RESOLUTION_X;		// Resolution the game was originally 'designed' for. We scale the HUD for any resolutions other than this.
        static const float REREFERNCE_RESOLUTION_Y;		// Resolution the game was originally 'designed' for. We scale the HUD for any resolutions other than this.

        //----------------------------------------------------------------------
        // Functions
        //----------------------------------------------------------------------

         Game( const char * playerName );       // Constructor: initialises the game
        ~Game();                                // Destructor: free up game resources

        void run();                 // Begins running the game
        void stop();                // Stops running the game
        void windowClosing();       // Event: window is about to close
        void windowRedrawing();     // Event: window needs to be redrawn. Do game loop here.

        // Pause and unpause the game. called when going in and out of menus

        void pause();
        void unpause();

        // Mouse press event:

        void mousePressed( int x , int y , GLWindow::MouseButton button );

        // Key pressed event:

        void keyboardPressed( GLWindow::KeyboardKey key );

        // Travel the player to another star system:

        void travelToSystem( unsigned sectorX , unsigned sectorY );

        // Reset player position to start positions in space and coming coming from docking:

        void setPlayerPosition_spaceStart();
        void setPlayerPosition_dockStart();

        // Gives the player of the game:

        inline PlayerHuman * getPlayer(){ return player; }

        // Gives the galaxy of the game:

        inline Galaxy * getGalaxy(){ return galaxy; }

        // Gives the current star system of the game that the player is in:

        inline StarSystem * getSystem(){ return system; }

        // Set the current star system of the game:

        void setSystem( const StarSystem & system , bool spawnEnemyShips ,  bool startInSpace );

        // Sets what ship the player has: game retains ownership of this object afterwards

        void setPlayerShip( GameObject_Ship * ship );

        // Spawns enemies around the player:

        void spawnEnemies();

        // Kills all enemies from the game: also kills

        void killEnemies();

        // Draws a simple loading screen:

        static void drawLoadingScreen();
        
        // Returns the amount to scale the GUI/HUD by. This is to deal with the various resolutions there are.
        
        static float getGuiScaleFactor();
        
        // Returns the 'effective resolution' of the game. Which is the reference resolution scaled by the GUI scale factor, plus extra bits at the sides (or top/bottom)
        
        static void getEffectiveResolution(float & resolutionX, float & resolutionY);

//##############################################################################
//##############################################################################
//##############################################################################
//##############################################################################

 protected:

        //----------------------------------------------------------------------
        // Constants
        //----------------------------------------------------------------------

        static const unsigned   FRAME_TIME_UPDATE_FRAMES;       // Number of frames over which the current frame rate is determined
        static const unsigned   GALAXY_SEED;                    // seed used for the randomnly generated galaxy
        static const float      GOOD_VALUE_DANGER_LEVEL;        // when the players goods are at this value, the danger level from having goods on board is at its highest
        static const float		BASE_GOOD_VALUE_DANGER_LEVEL;	// amount added to the goods danger level, regardless of what the player actually has
        static const float      BASE_DANGER_LEVEL;              // base danger level for anywhere in the game
        static const float      MISSILE_WARNING_SOUND_INTERVAL; // Time in between missile warning sounds
        static const float      DEATH_CAMERA_TIME;              // amount of time the death camera hovers around player ship when player has died
        static const float      DEATH_CAMERA_DISTANCE;          // distance from the players ship the death camera is
        static const float      DEATH_CAMERA_ROTATE_SPEED;      // how fast the death camera rotates around the players ship

        static const unsigned   MAX_AI_SHIPS = 16;              // the maximum number of ai ships that can attack the player after hyperspace
        static const float      AIPLAYER_START_DISTANCE;        // Distance from the space station the AI ships start at

        static const float      PLAYER_SPACE_START_DISTANCE;    // Distance from the space station the player will start at when coming out of hyperspace
        static const float      PLAYER_DOCK_START_POS_X;        // Player starting position for coming out of spacestation: x
        static const float      PLAYER_DOCK_START_POS_Y;        // Player starting position for coming out of spacestation: y
        static const float      PLAYER_DOCK_START_POS_Z;        // Player starting position for coming out of spacestation: z
        static const double     PLAYER_START_CREDITS;           // Amount of credits the player starts with

        static const float      HYPERSPACE_TIME;                // Time spent in the hyperspace interlude in seconds
        static const float      HYPERSPACE_CYLINDER_RADIUS;     // Sise of the hyperspace cylinder
        static const float      HYPERSPACE_CYLINDER_SLICES;     // Number of slices in the hyperspace cylinder
        static const float      HYPERSPACE_CYLINDER_LENGHT;     // Lenght of the hyperspace cylinder
        static const float      HYPERSPACE_TRAVEL_DISTANCE;     // How far the player travels through the hyperspace cylinder
        static const float      HYPERSPACE_TEXTURE_SCALE;       // The amount the texture coordinates of the hyperspace cylinder are scaled
        static const float      HYPERSPACE_TEXTURE_STRETCH;     // The amount to stretch the hyperspace texture over time
        static const float      HYPERSPACE_LAYER1_TURN_SPEED;   // Speed at which the texture of layer one rotates
        static const float      HYPERSPACE_LAYER2_TURN_SPEED;   // Speed at which the texture of layer one rotates

        //----------------------------------------------------------------------
        // Functions
        //----------------------------------------------------------------------

        // Draws the HUD for the in-game sections:

        void drawHud();

        // Draw the hyperspace jump interlude:

        void drawHyperspaceInterlude();

        // Find the closest missile targeted at the player

        GameObject * findClosestIncomingMissile();

        //----------------------------------------------------------------------
        // Variables
        //----------------------------------------------------------------------

        // Program

        bool continueRunning;    // continue running the game ?

        // World

        GameScene *     scene;              // The main game scene
        Galaxy *        galaxy;             // The games galaxy
        StarSystem *    system;             // current star system the player is in

        // Timing

        Timer *  frameTimer;            // The games frame timer
        float    frameTime;             // Current game frame time in seconds: updated every so often
        float    frameTimesAccum;       // Accumalted frame times for a number of frames
        unsigned frameTimesCounted;     // Number of frame times added to the accumalted frame times

        // Camera

        Camera *  deathCamera;        // The camera used to display the players ship after death
        float     deathCameraAngle;   // current rotation angle of the death camera about the y axis

        // Spacestation

        GameObjectHook * hookSpaceStation;      // Hook to the spacestation:

        // Player

        GameObjectHook * hookPlayerShip;        // Hook to the players ship:
        PlayerHuman    * player;                // The human player object
        float            timePlayerDead;        // The amount of time the player has been dead for: used when player dies
        float            lastPlayerX;           // last known player position: x
        float            lastPlayerY;           // last known player position: y
        float            lastPlayerZ;           // last known player position: z

        // GUI

        bool menuButtonSelected;        // was the menu button selected last time we checked ?
        bool missileButtonSelected;     // was the missile button selected last time we checked ?
        bool empButtonSelected;         // was the emp button selected last time we checked ?

        // AI

        PlayerAI       * aiPlayers[MAX_AI_SHIPS];       // The array of ai players
        GameObjectHook * aiShipHooks[MAX_AI_SHIPS];     // The array of hooks to ai ships:
        unsigned         numAIPlayers;                  // The number of ai players currently in the game

        // MISSILE WARNING

        float timeToMissileWarningSound;                // Time to the next missile warning noise

}; // end of: class Game{}

//##############################################################################
// C++ includes
//##############################################################################

#include "GLWindow.h"
#include "Timer.h"
#include "Camera.h"
#include "GameScene.h"
#include "GameObject.h"
#include "GameObjectHook.h"
#include "GameObject_SpaceStation.h"
#include "GameObject_Missile.h"
#include "GameObject_Ship.h"
#include "PlayerHuman.h"
#include "PlayerAI.h"
#include "Ships.h"
#include "GLFont.h"
#include "GLFontManager.h"
#include "GLTexture.h"
#include "GLTextureManager.h"
#include "GuiScreen_InGameMenu.h"
#include "Galaxy.h"
#include "SoundManager.h"
#include "SoundSystem.h"
#include "MusicSystem.h"

#endif // end of: ifndef GAME_H
