/*
	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 GAMEOBJECTSCENE_H
#define GAMEOBJECTSCENE_H

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

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

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

class Camera;
class GameObject;
class MovingGameObject;
class StaticGameObject;

//##############################################################################
//##############################################################################
//##############################################################################
//##############################################################################
//
//
// Class Name:   GameObjectScene
// Purpose:      Responsible for managing a scene full of game objects, contains
//               functions for moving the game objects and drawing them as well
//               as adding new objects or removing objects from the scene. One
//               of the base classes for the GameScene class which is a comprised
//               super class of many different types of scenes: lights, particles etc..
//               The game object scene is responsible for managing the memory of
//               every object added into the scene. However the scene does not manage
//               hook memory as this is the responsibility of the class which created
//               them.
//
//
//##############################################################################
//##############################################################################
//##############################################################################
//##############################################################################

class GameObjectScene
{
 public:

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

        // Constructor

        GameObjectScene();

        // Destructor

        ~GameObjectScene();

        // Object insertion / deletion:

        void addObject( GameObject * object );      // adds object into scene. deletes object on failure.
        void deleteObject( GameObject * object );   // deletes object from the scene. object is gone forever after this.

        // removes an object for the scene but does not delete it.

        void removeObject( GameObject * object );

        // Tells if a given object exists in the scene:

        bool objectExists( GameObject * object );

        // Trys to find the first instance of a given object type: returns null on failure.

        GameObject * findObject( const char * name );

        // Finds the next instance in the scene of the of the same type as given object: returns null on failure

        GameObject * findNextObject( const GameObject * object );

        // Add / delete a managed hook to a game object

        void addHook    ( GameObjectHook * hook );  // tries to add a hook into the scene. makes its pointer null on failure
        void removeHook ( GameObjectHook * hook );  // tries to remove a hook from the scene. does not delete the hook.

        // Move an object to a given position: if the object is movable then this function
        // also kills any non-indestructable moving objects that are in the way of this position:

        void setObjectPosition( GameObjectHook * hook , float x , float y , float z );

        // Returns a pointer to the 'best' target object from a given source object.
        // This decision is made by the angular closeness of a vector from the source
        // to target object to the forward vector of the source object. Function may
        // return null in the case where no suitable target is found.

        GameObject * getBestTargetForObject( GameObject * sourceObject );

        // Casts a ray from a given point and direction and returns what it hits
        // and where it hits- if it does hit anything at all. Precise ray casting
        // is used even for moving objects, instead of the simple bounding spheres
        // used for collision detection. Reutrns the object that was hit if anything
        // was hit or null on no hit. also fills in the position of hit if there was one.

        GameObject * rayCast
        (
            const GameObject  *  excludeObject,     // an object to exclude from the test: may be null
            const float       *  origin,            // point ray starts at
            const float       *  direction,         // direction ray goes in (does not need to be normalised)
            float             *  hitPoint           // 3d vector to save hit position to
        );

        // Does the same as the above function but only checks against one particular object.
        // Returns true if the object was hit by the ray, false otherwise.

        bool rayCastObject
        (
            GameObject  *  object,         // object to check against
            const float *  origin,         // point ray starts at
            const float *  direction,      // direction ray goes in (does not need to be normalised)
            float       *  hitPoint        // 3d vector to save hit position to
        );

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

 protected:

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

        void moveObjects( float frameTime );     // move all objects in the scene
        void drawObjects( Camera * camera );     // draw all objects in the scene

        // Dispatch the on frame to all objects in the scene:

        void dispatchEventOnFrame( float frameTime);

        // Dispatch the on draw event to all objects in the scene:

        void dispatchEventOnDraw( Camera * camera );

        // Collision test against a static object: assumes both objects are solid
        // and have meshes. Performs bounding sphere to polygon testing.

        void collisionStatic
        (
            MovingGameObject * collider ,   // object moving
            StaticGameObject * collidee     // object being tested against
        );

        // Collision test against a moving object: assumes both objects are solid
        // and have meshes. Performs bounding sphere to bounding sphere testing.

        void collisionMoving
        (
            MovingGameObject * collider ,   // object moving
            MovingGameObject * collidee     // object being tested against
        );
        
        // Builds safe iteration cache. Done before iteration through a series of objects. E.G dispatching the OnFrame event.
        
        void BuildSafeIterationCache();
        
        // Destroys the safe iteration cache. Required to free up hook slots. Done after iteration through a series of objects is finshed.
        
        void DestroySafeIterationCache();

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

 private:

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

        static const unsigned MAX_OBJECTS	= 512;			// maximum number of objects in the object arrays
        static const unsigned MAX_HOOKS		= 2048;			// maximum number of hooks to game objects

        // Determines how much objects rebound off each other upon collision

        static const float STATIC_COLLISION_ELASTICITY;     // for sphere polygon collisions
        static const float MOVING_COLLISION_ELASTICITY;     // for sphere sphere collision

        // Determines how much velocity loss is needed in a static collision before damage occurs or a noise is played:

        static const float MIN_STATIC_COLLISION_VELOCITY_LOSS;

        // Determines how much velocity is needed when two moving objects collide before damage happens

        static const float MIN_MOVING_COLLISION_VELCITY;

        // Determines how much damage loosing velocity on collision does to an object in a static collision

        static const float STATIC_COLLISION_VELOCITY_LOSS_DAMAGE;

        // Determines how much velocity damages objects in a moving object collision

        static const float MOVING_COLLISION_VELOCITY_DAMAGE;

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

        // Game object arrays: static and moveable objects

        MovingGameObject ** movingObjects;
        StaticGameObject ** staticObjects;

        // Array of pointers to hook objects

        GameObjectHook ** hooks;

        // Number of objects in both moving and static arrays

        unsigned movingObjectCount;
        unsigned staticObjectCount;

        // Number of hooks in the game object scene

        unsigned hookCount;
        
        //'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        // Temporary data used to safely iterate the object collections in spite of deletions.
        // Without this there is the potential for bad things to happen if objects delete themselves
        // or other objects whilst this manager is iterating throught the object collections.
        //'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        
        struct SafeIterationCache
        {
			// This memory stores hook objects that point to static game objects
			
			char static_hook_mem[ sizeof(GameObjectHook) * MAX_OBJECTS ];
			
			// This memory stores hook objects that point to moveable game objects
			
			char moving_hook_mem[ sizeof(GameObjectHook) * MAX_OBJECTS ];
			
			// This stores a convience pointer to 'static_hook_mem'
			
			GameObjectHook * static_hooks;

			// This stores a convience pointer to 'dynamic_hook_mem'
			
			GameObjectHook * moving_hooks;
			
			// Static object count, before iteration began: used to keep the number of hooks
			
			unsigned original_static_count;
			
			// Moving object count, before iteration began: used to keep the number of hooks
			
			unsigned original_moving_count;
        
        } safeIterationCache;
        
}; // end of: class GameObjectScene{}

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

#include "Camera.h"
#include "GameObject.h"
#include "GameObjectHook.h"
#include "MovingGameObject.h"
#include "StaticGameObject.h"

#endif // end of: ifndef GAMEOBJECTSCENE_H
