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

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

class Camera;
class Mesh;
class GameObjectScene;

//##############################################################################
//##############################################################################
//##############################################################################
//##############################################################################
//
//
// Class Name:   GameObject
// Purpose:      Very important class that serves as a base class for the two
//               main types of objects in the game, moving and static objects.
//               These two sub classes then in turn serve as the basis for every
//               single object in the game. The game scene is the manager of all
//               game objects and thus has access to all its private data.
//
//
//##############################################################################
//##############################################################################
//##############################################################################
//##############################################################################

class GameObject
{
    //--------------------------------------------------------------------------
    // GameObjectScene manages all objects. Needs private access.
    //--------------------------------------------------------------------------

    friend class GameObjectScene;

 public:

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

        // Constructor for game object base class

        GameObject
        (
            float       pos_x,      // initial position: x
            float       pos_y,      // initial position: y
            float       pos_z,      // initial position: z
            Mesh    *   mesh        // object's mesh
        );

        // Destructor: does not have to be implemented

        virtual ~GameObject(){;}

        // Reset the objects orientation to default orientation:

        void resetOrientation();

        // Damages the object by the given amount: also gives object which damaged this object- but may be null.

        void damage( float amount , GameObject * damager );

        // 6DOF rotations within objects own coord system about a certain axis. All angles in radians.

        void rotateX( float angle );
        void rotateY( float angle );
        void rotateZ( float angle ); 
        
        // No unreferenced param warning
        
        #pragma warning(disable:4100)        

        // Object event handlers for various game events: do not have to be implemented

        virtual void onCollide      ( GameObject * collider )    {;}    // event called for collision with another object
        virtual void onFrame        ( float frameTime       )    {;}    // event called once every frame before movement
        virtual void onDraw         ( Camera * camera       )    {;}    // event called when its time to draw the object
        virtual void onDamage       ( GameObject * damager  )    {;}    // event called when another objects weapons damage this object        
        
		// Restore this to normal
            
		#pragma warning(default:4100)        

        virtual void onSceneEnter (){;} // called when the object is put into a scene
        virtual void onSceneRemove(){;} // called when the object is taken out of a scene but not deleted. scene is still valid for duration of the call.

        // Get position:

        inline float getPosX() const { return position[0]; }       // get objects position: x
        inline float getPosY() const { return position[1]; }       // get objects position: y
        inline float getPosZ() const { return position[2]; }       // get objects position: z

        inline void getPosition ( float * position ) const
        {
            position[0] = this->position[0];
            position[1] = this->position[1];
            position[2] = this->position[2];
        }

        // Retrieve the three object coordinate system axes

        inline void getAxisX ( float * vector ) const
        {
            vector[0] = this->orientation[0];
            vector[1] = this->orientation[1];
            vector[2] = this->orientation[2];
        }

        inline void getAxisY ( float * vector ) const
        {
            vector[0] = this->orientation[3];
            vector[1] = this->orientation[4];
            vector[2] = this->orientation[5];
        }

        inline void getAxisZ ( float * vector ) const
        {
            vector[0] = this->orientation[6];
            vector[1] = this->orientation[7];
            vector[2] = this->orientation[8];
        }

        // Get 3x3 orientation matrix for object:

        void getOrientationMatrix( float * matrix ) const;

        // Sets the objects orientation matrix to the 3x3 matrix given:

        void setOrientationMatrix( float * matrix );

        // Converts the given world position into the objects local coordinate system:

        void toObjectCoordinates( float * position ) const;

        // Make this object face towards a given point in world coordinates

        void facePoint( const float * point );

        // Same as face point, but puts a limitation on the rotation (in radians) to face the point

        void facePoint( const float * point , float maxRotation );

        // Makes the object face towards another given object:

        void faceObject( const GameObject * object );

        // Same as face object, but puts a limitation on the rotation (in radians) to face the point

        void faceObject( const GameObject * object , float maxRotation );

        // Gets the distance to the given object:

        float distanceTo( const GameObject * object );

        // Gets the square distance to the given object:

        float squareDistanceTo( const GameObject * object );

        // Get the scene the object belongs to:

        inline GameObjectScene * getScene() const { return this->scene; }

        // Set whether the object is visible or not

        inline void setVisible( bool visible ){ this->visible = visible; }

        // Set whether the object is solid or not

        inline void setSolid( bool solid ){ this->solid = solid; }

        // See whether the object is visible or not

        inline bool isVisible() const { return visible; }

        // See whether the object is solid or not

        inline bool isSolid() const { return solid ;}

        // Get the objects health:

        inline float getHealth() const { return health; }

        // Set the objects health:

        inline void setHealth( float health ) { this->health = health; }

        // Get the objects mesh

        inline const Mesh * getMesh() const { return mesh; }

        // Get the objects name

        inline const char * getName() const { return name; }

        // Is the object targetable ?

        inline bool isTargetable(){ return targetable; }

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

 protected:

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

        // Derived classes must explain themselves by implementing this simple function

        virtual bool isStatic() = 0;

        //----------------------------------------------------------------------
        // Data
        //----------------------------------------------------------------------

        float   health;                 // amount of damage object can take till it dies
        bool    indestructable;         // whether the object is indestructable or not
        bool    visible;                // draw the object or not ?
        bool    solid;                  // is the object solid ? can it move through objects ?

        // Object name:

        const char * name;

        // Whether or not the object can be targeted by the player

        bool targetable;

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

 private:

        //----------------------------------------------------------------------
        // Data
        //----------------------------------------------------------------------

        float    position[3];       // the objects position
        float    orientation[9];    // 3x3 matrix describing the objects orientation
        Mesh  *  mesh;              // the mesh the object uses: may be null

        // GameObject scene helper variables:

        GameObjectScene *   scene;              // game scene to which the object belongs
        unsigned            sceneArrayPos;      // position in the game scene object array

}; // end of: class GameObject{}

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

#include "Camera.h"
#include "Mesh.h"
#include "GameObjectScene.h"

#endif // end of: ifndef GAMEOBJECT_H
