/*
	Trampoline Sim.
	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_H
#define GAME_H

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

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

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

namespace Game
{
	//=================================================================================================================
	//=================================================================================================================
	
	class Window;
	class PixelShaderManager;
	class VertexShaderManager;
	class TextureManager;
	class GameObjectManager;
	class Camera3D;
	class BufferedLineRenderer;
	class SimulationWorld;
	
	//=================================================================================================================
	/// @brief		This is the core game class. Handles the high level game logic.
	//=================================================================================================================

	class GameCore : public WindowEventListener
	{
		public:

			//=========================================================================================================
			// Constants
			//=========================================================================================================
			
				/// Title for the game
				
				static const char * GAME_TITLE;
			
				/// Near plane value for the camera
				
				static const float CAM_Z_NEAR;
				
				/// Far plane value for the camera
				
				static const float CAM_Z_FAR;
								
				/// Target refresh interval in between game ticks - in seconds.
				
				static const float FRAME_INTERVAL;
				
				/// Maximum number of frames that we can try to make up from frame skipping if we are behind real time
				
				static const unsigned MAX_CATCHUP_FRAMES;

			//=========================================================================================================
			// 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 game object manager
				
				inline GameObjectManager * GetObjectManager(){ return m_game_object_manager; } 
				
				/// Gets the buffered line renderer used by the game
				
				inline BufferedLineRenderer * GetBufferedLineRenderer(){ return m_buffered_line_renderer; }

				/// Returns the simulation world

				inline SimulationWorld * GetSimulationWorld(){ return m_sim_world; }
				
				/// 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 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; }

		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

				void DoCameraMovement();

				/// Does mouse input

				void DoMouseInput();
				
				/// Populates the scene with the plane and the box
				
				void PopulateScene();		

			//=========================================================================================================
			// Variables
			//=========================================================================================================
			
				/// Pointer to an instance of the game
				
				static GameCore * s_this;
				
				/// Window used by the game 
				
				Window * m_window;
				
				/// Time since the last update
				
				float m_time_since_update;
				
				/// Was the last frame rendered ? 
				
				bool m_rendered_last_frame;

				/// True if the left mouse button was clicked last time

				bool m_left_mouse_clicked;

				/// Camera used by the game

				Camera3D * m_camera;
				
				/// Texture manager
				
				TextureManager * m_texture_manager;
				
				/// Pixel shader manager
				
				PixelShaderManager * m_pixel_shader_manager;
				
				/// Vertex shader manager
				
				VertexShaderManager * m_vertex_shader_manager;	
				
				/// Game object manager for the game
				
				GameObjectManager * m_game_object_manager;
				
				/// 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 line renderer used to draw lines quickly in batches

				BufferedLineRenderer * m_buffered_line_renderer;
				
				/// Physics simulation world
				
				SimulationWorld * m_sim_world;

				/// True if tab was pressed during the last frame

				bool m_tab_pressed;
	};
};

#endif
