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

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

class Mesh;
class GameScene;
class GameObject_Explosion;
class GameObject_Missile;
class GameObject_Emp;
class Sound;
class SoundManager;

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

#include "MathLibrary.h"

//##############################################################################
// Stuff that cannot be forward referenced
//##############################################################################

#include "MovingGameObject.h"
#include "GoodsInventory.h"
#include "Laser.h"

//##############################################################################
//##############################################################################
//##############################################################################
//##############################################################################
//
//
// Class Name:   GameObject_Ship
// Purpose:      Class that describes a ship.
//
//
//##############################################################################
//##############################################################################
//##############################################################################
//##############################################################################

class GameObject_Ship : public MovingGameObject
{

 public:

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

        // Constructor for ship object

        GameObject_Ship
        (
            float       pos_x,                  // initial position: x
            float       pos_y,                  // initial position: y
            float       pos_z,                  // initial position: z
            float       cost,                   // cost of the ship
            float       health,                 // amount of damage the ship can take.
            float       maxSpeed,               // maximum speed of the ship
            float       acceleration,           // amount of acceleration the ship has. higher values mean more resposive handling.
            float       mass,                   // mass of the object
            float       hyperspaceRange,        // distance the ship can travel in light years. each sector is a square light year in size
            unsigned    cargoCapacity,          // the amount of goods units the ship can hold
            unsigned    maxMissiles,            // maximum number of missiles the ship can have
            unsigned    maxEmpBombs,            // maximum number of emp bombs the ship can have
            float       laserStrenght,          // ships's laser strenght
            float       laserCoolingAmount,     // ships's laser cooling amount
            float       laserColorR,            // ships's laser color: red
            float       laserColorG,            // ships's laser color: green
            float       laserColorB,            // ships's laser color: blue
            float       laserStartX,            // Where in ship coordinates (X) the ships laser starts firing from
            float       laserStartY,            // Where in ship coordinates (Y) the ships laser starts firing from
            float       laserStartZ,            // Where in ship coordinates (Z) the ships laser starts firing from
            float       particleSpawnX,         // Where to start spawing particles at: x in ship coordinates
            float       particleSpawnY,         // Where to start spawing particles at: y in ship coordinates
            float       particleSpawnZ,         // Where to start spawing particles at: z in ship coordinates
            float       cameraCockpitX,         // Where in ship coordinates (X) the cockpit view of the camera is located
            float       cameraCockpitY,         // Where in ship coordinates (Y) the cockpit view of the camera is located
            float       cameraCockpitZ,         // Where in ship coordinates (Z) the cockpit view of the camera is located
            Mesh    *   mesh                    // ships's mesh.
        );

        // Destructor for the ship object: makes an explosion

        ~GameObject_Ship();

        // On frame event: spawns particles

        void onFrame( float frameTime );

        // On draw event: draws a laser beam if the ship is firing:

        void onDraw( Camera * camera );

        // On scene enter event:

        void onSceneEnter();

        // On scene remove event:

        void onSceneRemove();

        // Speed up or slow down the ship: increases / decreases ships target speed

        void accelerate( float amount );

        // Fires the ships lasers

        void fireLasers( float frameTime );

        // Fires the ships lasers and randomly varies where the beam goes a little:

        void fireLasers( float frameTime , float randomness );

        // Cools the ships lasers

        void coolLasers( float frameTime );

        // Resets the ships laser heat

        void resetLaserHeat();

        // Fire a missile at a target:

        void fireMissile( GameObject * target );

        // Deploy an emp bomb:

        void deployEmp();

        // Sets the number of missiles the ship has: will not allow over the maximum amount.

        void setNumMissiles( unsigned numMissiles );

        // Sets the number of emp bombs the ship has: will not allow over the maximum amount.

        void setNumEmpBombs( unsigned numEmpBombs );

        // Refuels the ship and gives fuel for hyperspace jump:

        inline void refuel() { this->hasHyperspaceFuel = true; }

        // Uses up the ship's hyperspace fuel:

        inline void spendFuel() { this->hasHyperspaceFuel = false; }

        // See if the ship has hyperspace fuel:

        inline bool hasFuel() const { return this->hasHyperspaceFuel; }

        // Get the maximum speed of the ship

        inline float getMaxSpeed() const { return maxSpeed; }

        // Get the maximum health of the ship

        inline float getMaxHealth() const { return maximumHealth; }

        // Get the laser heat of the ship:

        inline float getLaserHeatLevel() const { return laser.getHeat(); }

        // Ge the hyperspace range of the ship

        inline float getHyperspaceRange() const { return hyperspaceRange; }

        // Gets a pointer to the ships laser:

        inline Laser * getLaser(){ return &laser; }

        // Get the goods inventory of the ship:

        inline GoodsInventory * getGoodsInventory(){ return &goodsInventory; }

        // Get the cargo capacity of the ship in units:

        inline unsigned getCargoCapacity() const { return cargoCapacity; }

        // Get the number of missiles the ship can carry:

        inline unsigned getMaxMissiles() const { return maxMissiles; }

        // Get the number of missiles the ship currently has:

        inline unsigned getNumMissiles() const { return numMissiles; }

        // Get the number of emp bombs the ship can carry:

        inline unsigned getMaxEmpBombs() const { return maxEmpBombs; }

        // Get the number of emp bombs the ship currently has:

        inline unsigned getNumEmpBombs() const { return numEmpBombs; }

        // Get the position of the cockpit camera in ship coordinates:

        inline void getCockitCameraPosition( float * position )
        {
            if ( position )
            {
                position[0] = cameraCockpitX;
                position[1] = cameraCockpitY;
                position[2] = cameraCockpitZ;
            }
        }

        // Get the cost of the ship

        inline float getCost(){ return cost; }

        // Set the cargo of the ship

        inline void setCargo( const GoodsInventory & cargo )
        {
            this->goodsInventory = cargo;
        }

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

 protected:

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

        static const float      EXPLOSION_TIME;                         // time the ship explosion lasts for in seconds
        static const float      EXPLOSION_SCALE;                        // scale of the ship explosion
        static const float      ENGINE_PARTICLE_INTERVAL;               // amount of time in seconds between bursts of particles coming from the engine
        static const float      ENGINE_PARTICLE_TIME1;                  // engine particle live time 1
        static const float      ENGINE_PARTICLE_TIME2;                  // engine particle live time 2
        static const float      ENGINE_PARTICLE_COLOR1_R;               // engine particle color: red
        static const float      ENGINE_PARTICLE_COLOR1_G;               // engine particle color: green
        static const float      ENGINE_PARTICLE_COLOR1_B;               // engine particle color: blue
        static const float      ENGINE_PARTICLE_COLOR2_R;               // engine particle color: red
        static const float      ENGINE_PARTICLE_COLOR2_G;               // engine particle color: green
        static const float      ENGINE_PARTICLE_COLOR2_B;               // engine particle color: blue
        static const float      ENGINE_PARTICLE_SIZE1;                  // the size of engine particles
        static const float      ENGINE_PARTICLE_SIZE2;                  // the size of engine particles
        static const float      ENGINE_PARTICLE_DIR_RANDOMNESS;         // amount of variation from ships velocity direction particles can go
        static const float      ENGINE_PARTICLE_VEL_RANDOMNESS;         // amount of variation from ships velocity amount particles can have
        static const float      ENGINE_PARTICLE_CONST_VEL_RANDOMNESS;   // amount of random variation in particle velocity to apply, regardless of ships speed
        static const unsigned   ENGINE_PARTICLE_COUNT;                  // number of particles to create in an engine particle stream

        static const float      ENGINE_NOISE_DISTANCE;                  // distance from which the ships engines can be heard
        static const float      ENGINE_NOISE_MIN_PITCH;                 // minimum pitch of the ships engines
        static const float      ENGINE_NOISE_MAX_PITCH;                 // maximum pitch of the ships engines

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

        // Spawn the engine particles for the ship:

        void spawnEngineParticles();

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

        float       cost;                     // how much the ship costs
        bool        hasHyperspaceFuel;        // does the ship have fuel for a hyperspace jump ?
        bool        useLeftMissileBay;        // use the left missile bay when firing or the right missile bay ?
        unsigned    cargoCapacity;            // the amount of goods units the ship can hold
        float       lastFrameTime;            // time of the last frame in seconds
        float       maximumHealth;            // maximum health the ship can have
        float       maxSpeed;                 // maximum speed of the ship the ship is allowed to go at
        float       hyperspaceRange;          // range of the ships hyperspace engine in light years
        unsigned    numMissiles;              // number of missiles the ship currently has
        unsigned    maxMissiles;              // maximum number of missiles the ship can have
        unsigned    numEmpBombs;              // number of emp bombs the ship currently has
        unsigned    maxEmpBombs;              // maximum number of emp bombs the ship can have
        float       timeToEngineParticles;    // the amount of time left in seconds till ship creates another set of engine particles

        // Where to spawn particles: in ship coordinates

        float particleSpawnX;
        float particleSpawnY;
        float particleSpawnZ;

        // Where the ships laser beam starts from: in ship coordinates

        float laserStartX;
        float laserStartY;
        float laserStartZ;

        // Where the ships cockpit views is: in ship coordinates

        float cameraCockpitX;
        float cameraCockpitY;
        float cameraCockpitZ;

        // Laser which the ship has:

        Laser laser;

        // Goods inventory of the ship:

        GoodsInventory goodsInventory;

        // The sound id of the ship engine noise

        unsigned shipEngineSoundID;

}; // end of: class GameObject_Ship{}

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

#include "Mesh.h"
#include "GameScene.h"
#include "GameObject_Explosion.h"
#include "GameObject_Missile.h"
#include "GameObject_Emp.h"
#include "Sound.h"
#include "SoundManager.h"

#endif // end of: ifndef GAMEOBJECT_SHIP_H
