/*
	Lan Wars.
	Copyright (c) 2009, 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_CORE_H
#define GAME_CORE_H

//=====================================================================================================================
//=====================================================================================================================

#include "Windows\Window.h"
#include "Windows\WindowEventListener.h"
#include "Game\GameFrameTimer.h"

//=====================================================================================================================
//=====================================================================================================================

namespace Game
{
	//=================================================================================================================
	//=================================================================================================================
	
	class Window;
	class PixelShaderManager;
	class VertexShaderManager;
	class TextureManager;
	class BitmapFontManager;
	class GameObjectManager;
	class Camera3D;
	class PrimitivesRenderer;
	class BufferedPointRenderer;
	class BufferedLineRenderer;
	class SpriteRenderer;
	class GameHud;
	class BitmapFont;
	class GamePostFX;
	class ParticleEmitter;
	class GameMenus;
	class GameSession;
	class GameSpriteBank;
	
	//=================================================================================================================
	/// @brief		This is the core game class. Handles the high level game logic.
	/// @todo		Allow camera movement on the server for spectating
	//=================================================================================================================

	class GameCore : public WindowEventListener
	{
		public:

			//=========================================================================================================
			// Constants
			//=========================================================================================================
			
				/// Title for the game
				
				static const char * GAME_TITLE;
				
				#ifdef USE_DEBUG_CONSOLE
				
					/// Title for the debug console

					static const char * DEBUG_CONSOLE_TITLE;
					
				#endif
			
				/// Near plane value for the camera
				
				static const float CAM_Z_NEAR;
				
				/// Far plane value for the camera
				
				static const float CAM_Z_FAR;
				
				/// Native view area: any screen resolutions other than this are scaled - keeping aspect correctness
				
				static const Vec2i NATIVE_RES;				
			
			//=========================================================================================================
			// Functions
			//=========================================================================================================
		
				/// Creates the game

				GameCore( Window * window );
				
				/// Destroys the game
				
				~GameCore();
				
				/// Gets the instance of the game
				
				static inline GameCore * GetSingleton(){ return s_this; }

				/// Tells the object to announce it's type name: this is the type name without the Game:: namespace

				virtual const char * GetTypeName() const;
				
				/// Gets the camera
				
				inline Camera3D * GetCamera(){ return m_camera; }
				
				/// Gets the texture manager
				
				inline TextureManager * GetTextureManager(){ return m_texture_manager; }
				
				/// Gets the vertex shader manager
				
				inline VertexShaderManager * GetVertexShaderManager(){ return m_vertex_shader_manager; }
				
				/// Gets the pixel shader manager
				
				inline PixelShaderManager * GetPixelShaderManager(){ return m_pixel_shader_manager; }
				
				/// Gets the bitmap font manager
				
				inline BitmapFontManager * GetBitmapFontManager(){ return m_bitmap_font_manager; }				
				
				/// Gets the game object manager
				
				inline GameObjectManager * GetObjectManager(){ return m_game_object_manager; } 
				
				/// Gets the primitives renderer
				
				inline PrimitivesRenderer * GetPrimitivesRenderer(){ return m_primitives_renderer; }

				/// Gets the buffered point renderer used by the game

				inline BufferedPointRenderer * GetBufferedPointRenderer(){ return m_buffered_point_renderer; }
				
				/// Gets the buffered line renderer used by the game
				
				inline BufferedLineRenderer * GetBufferedLineRenderer(){ return m_buffered_line_renderer; }

				/// Gets the sprite renderer used by the game
				
				inline SpriteRenderer * GetSpriteRenderer(){ return m_sprite_renderer; }
				
				/// Gets the sprite bank used by the gmae
				
				inline GameSpriteBank * GetSpriteBank(){ return m_sprite_bank; }
				
				/// Gets the font used by the game
				
				inline BitmapFont * GetFont(){ return m_font; }
				
				/// Gets the smaller font used by the game for rendering larger amounts of text
				
				inline BitmapFont * GetSmallFont(){ return m_small_font; }
							
				/// Window redraw event - does the game loop
				
				virtual void OnWindowRedrawing();
				
				/// Window event - when a key is released
				
				virtual void OnKeyboardReleased( Keyboard::Key key_code );
				
				/// Gets the window used by the game:
				
				inline Window * GetWindow(){ return m_window; }			
				
				/// Returns the display for the game
				
				inline Display * GetDisplay(){ return m_window->GetDisplay(); }
				
				/// Returns the random number generator used by the game
				
				inline Random & GetRandom(){ return m_random; }
				
				/// Returns the stack used by the game for temporary storage
				
				inline Stack & GetStack(){ return m_stack; }

				/// Returns the secondary stack used by the game for temporary storage
				
				inline Stack & GetSecondaryStack(){ return m_secondary_stack; }
				
				/// Gets the menus used by the game
				
				inline GameMenus * GetMenus(){ return m_menus; }
				
				/// Gets the network session for the game
				
				inline GameSession * GetSession(){ return m_session; }
				
				/// Called when the window gains focus
				
				virtual void OnWindowFocusGained();

		private:
		
			//=========================================================================================================
			// Functions
			//=========================================================================================================
			
				/// Called when the game is to do an update
				
				void OnUpdate();
				
				/// Called when the game is to do a render
				
				void OnRender();
				
				/// Does camera movement for the server
				
				void ServerCameraMovement();
				
				#ifdef USE_DEBUG_CONSOLE				
					
					/// Debug only console command: enables / disables profiling of updates
				
					static bool ConCmd_G_Profile( bool arg , bool arg_given );
					
					/// Debug only console command: enables / disables profiling of rendering
				
					static bool ConCmd_R_Profile( bool arg , bool arg_given );

					/// Debug only console command: enables / disables collision with the server camera
				
					static bool ConCmd_G_ServerCamCollide( bool arg , bool arg_given );
				
				#endif			

			//=========================================================================================================
			// Variables
			//=========================================================================================================

				/// This object determines when we should do updates etc.

				GameFrameTimer m_frame_timer;
			
				/// Random number generator used by the game
				
				Random m_random;						
			
				/// Pointer to an instance of the game
				
				static GameCore * s_this;
				
				/// Window used by the game 
				
				Window * m_window;				

				/// Camera used by the game

				Camera3D * m_camera;

				/// HUD for the game

				GameHud * m_hud;
				
				/// Texture manager
				
				TextureManager * m_texture_manager;
				
				/// Pixel shader manager
				
				PixelShaderManager * m_pixel_shader_manager;
				
				/// Vertex shader manager
				
				VertexShaderManager * m_vertex_shader_manager;
				
				/// Bitmap font manager
				
				BitmapFontManager * m_bitmap_font_manager;
				
				/// Game object manager for the game
				
				GameObjectManager * m_game_object_manager;
				
				/// A basic primitives renderer that can be used by all objects
				
				PrimitivesRenderer * m_primitives_renderer;
				
				/// A stack that can be used by game objects for various purposes. Allocated size is 1MB
				
				Stack m_stack;

				/// A secondary stack that can be used by game objects for various purposes. Allocated size is 1MB
				
				Stack m_secondary_stack;
			
				/// A buffered point renderer used to draw points quickly in batches

				BufferedPointRenderer * m_buffered_point_renderer;
				
				/// A buffered line renderer used to draw lines quickly in batches

				BufferedLineRenderer * m_buffered_line_renderer;

				/// A sprite renderer used to draw sprites

				SpriteRenderer * m_sprite_renderer;
								
				/// Bitmap font used for drawing text
				
				BitmapFont * m_font;
				
				/// A smaller font for larger amounts of text
				
				BitmapFont * m_small_font;
				
				/// The menus for the game
				
				GameMenus * m_menus;
				
				/// The sprite bank used by the game
				
				GameSpriteBank * m_sprite_bank;
				
				//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
				/// Network session for the game: controls the sending and receiving of all network data and controls 
				/// the high level state of the game - such as when a game starts and when a game ends.
				//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
				
				GameSession * m_session;
				
				#ifdef USE_DEBUG_CONSOLE
					
					/// Debug only flag. Profile rendering ?
					
					static bool s_profile_render;
					
					/// Debug only flag. Profile update ?
					
					static bool s_profile_update;
					
					/// Debug only flag. Do collision for the server camera ?
					
					static bool s_server_cam_collide;					
					
				#endif
	};
};

#endif
