/*
	Trig Wars.
	Copyright (c) 2008, 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 BULLET_BASE_H
#define BULLET_BASE_H

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

#include "GameObjects\MoveableObject.h"

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

namespace Game
{
	//=================================================================================================================
	//=================================================================================================================
	
	class BulletManager;

	//=================================================================================================================
	/// @brief		Base class for all bullet objects. Bullets are collide as points, though are drawn as lines 
	///				(or something else possibly) within the game.
	//=================================================================================================================

	class BulletBase : public MoveableObject , public Poolable
	{
		public:

			//=========================================================================================================
			// Functions
			//=========================================================================================================
			
				//=====================================================================================================
				/// @brief		Creates the bullet
				/// @param		damage - the amount of damage that the bullet does
				/// @param		speed - speed that this bullet type can travel at
				/// @pre		Damage must not be less than zero
				/// @pre		Speed must be > 0
				//=====================================================================================================
				
				BulletBase( float damage , float speed ) : MoveableObject(1.0f)
				{
					// Make sure ok:
				
					ENSURE( damage >= 0 , "Damage must not be less than zero"	);
					ENSURE( speed > 0	, "Speed must be > 0"					);
					
					// Set damage and speed
					
					m_damage = damage;
					m_speed	 = speed;
					
					// No bullet manager
					
					m_manager = 0;
				}
				
				#ifdef DEBUG
				
					//=================================================================================================
					/// @brief		Destructor. Frees up the bullet. This destructor is only used in debug.
					/// @pre		The bullet should no longer be marked as being part of a manager
					//=================================================================================================								
					
					virtual ~BulletBase()
					{
						// Make sure this is ok:
						
						ENSURE( m_manager == 0 , "The bullet should no longer be marked as being part of a manager" );
					}			
				
				#endif	
				
				//=====================================================================================================
				/// @brief		Fires the bullet at a given position and with a given velocity. Bullet's dead status is 
				///				reset after this.
				/// @param		pos - position to fire at
				/// @param		angle - direction to fire the bullet in
				/// @param		base_speed - base speed of the bullet, this should be set to the speed of the 
				///				firing object so that the bullet never 'lags' behind the firer
				/// @pre		Angular velocity of the bullet should be left at 0
				/// @pre		Linear friction of the bullet should be left at 1
				/// @pre		The bullet should have a bullet manager before firing
				//=====================================================================================================
				
				inline void Fire( const Vec2f & pos , float angle , float base_speed )
				{
					// Make sure ok:
										
					ENSURE( GetAngularVelocity() == 0	, "Angular velocity of the bullet should be left at 0"		);
					ENSURE( GetLinearFriction() == 1	, "Linear friction of the bullet should be left at 1"		);
					ENSURE( m_manager != 0				, "The bullet should have a bullet manager before firing"	);
				
					// Not dead
								
					m_is_dead = false; 
					
					// Set position and angle:
					
					SetPosition(pos); SetAngle(angle);
					
					// And velocity:
					
					SetLinearVelocity
					( 
						Vec2f( Float::Cos(angle), Float::Sin(angle) ) * ( m_speed + base_speed )
					);
				}
				
				/// Tells if the bullet is dead
				
				inline bool IsDead(){ return m_is_dead; }
				
				/// Tells how much damage the bullet does
				
				inline float GetDamage(){ return m_damage; }
				
				/// Tells how fast the bullet travels at
				
				inline float GetSpeed(){ return m_speed; }
				
				//=====================================================================================================
				/// @brief		Sets the bullet manager used by the bullet:
				/// @param		mgr - manager which is to manage the bullet
				/// @remarks	The bullet does not add a reference to it's manager because
				///				of the circular reference counting problem. Therefore the 
				///				manager should not be deleted during the lifetime of the bullet
				//=====================================================================================================
				
				inline void SetManager( BulletManager * mgr ){ m_manager = mgr; }
				
				/// Gets the bullet manager used by the bullet
				
				inline BulletManager * GetBulletManager(){ return m_manager; }
				
				//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
				/// Moves the bullet and does collision with enemies etc. This is used instead of regular OnUpdate()
				/// because the view area is given to the bullet here and is calculated beforehand.
				//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
				
				virtual void BulletUpdate
				( 
					float			delta_time	, 
					const Vec2f &	cam_pos		, 
					const Vec2f &	view_bl		, 
					const Vec2f &	view_tr 
					
				) = 0;			
				
		protected:
		
			//=========================================================================================================
			// Variables
			//=========================================================================================================
			
				/// The bullet manager this bullet belongs to
				
				BulletManager * m_manager;
			
				/// True if the bullet is dead. Bullet dies if it hits a target or if it is offscreen for a certain amount of time
				
				bool m_is_dead;
				
				/// The amount of damage that the bullet does
				
				float m_damage;
				
				/// Speed that the bullet can travel at
				
				float m_speed;
	};
};

#endif
