/*********************************************************************//**
*	Manazer zbrani
*	Manager ovlada vsechny zbrane. Provadi nastavovani zbrani, jejich vymenu
*	za dalsi v inventari, provadi utoky, nabijeni. Dale spousti vykreslovani
*	zbrane a jeji aktualizace. Navic vytvari efekt odporu zbrane.
*
*	author: Michal Jirous
*	date: 9.12.2008
*	file: ctrl_weapon_manager.cpp
**********************************************************************/

#include "ctrl_weapon_manager.h"
#include "weapons.h"
#include <sstream>
#include "parsing.h"
#include "game.h"


weapon_manager::CWeaponManager weapon_manager::weaponManager;
bool weapon_manager::commandsActivity[COMMAND_COUNT];

using namespace weapon_manager;
using namespace std;

/** @param param Nepouziva se. */
void weapon_manager::nextweapon( void * param )
{
	if( !game.m_pPlayer )
		return;

	const unsigned int curr = weaponManager.getCurrentWeapon();
	unsigned newWpn = curr;
	while(true)
	{
		++newWpn;
		if( newWpn == WEAPONS_COUNT )
			newWpn = 0;
	
		if( newWpn == curr )
			break;

		BasicWeapon *pWeapon_new = game.m_pPlayer->AmmoAndWeapons.getWeapon( newWpn );
		if( pWeapon_new && pWeapon_new->isOwned() )
		{
			weaponManager.setWeapon( newWpn );
			break;
		}
	
	}
}

/** @param param Nepouziva se. */
void weapon_manager::prevweapon( void * param )
{
	if( !game.m_pPlayer )
		return;

	const unsigned int curr = weaponManager.getCurrentWeapon();
	unsigned newWpn = curr;
	while(true)
	{
		if( newWpn == 0 )
			newWpn = WEAPONS_COUNT;
	
		--newWpn;

		if( newWpn == curr )
			break;

		BasicWeapon *pWeapon_new = game.m_pPlayer->AmmoAndWeapons.getWeapon( newWpn );
		if( pWeapon_new && pWeapon_new->isOwned() )
		{
			weaponManager.setWeapon( newWpn );
			break;
		}
	
	}
}

/** @param param Parameter ukazujici na istringstream objekt, kde se precte jmeno zbrane v textove podobe. */
void weapon_manager::setweapon( void *param )
{
	istringstream *strIn = (istringstream*)param;
	string filename = parsing::readPosibleQuotedCommandParm( *strIn );

	unsigned int curr = getWeaponId( filename );
	weaponManager.setWeapon( curr );
}

/** @param param Parameter ukazujici na hodnotu typu int, kde 1 znamena aktivovano a 0 deaktivovano. */
void weapon_manager::attack( void *param )
{
	if( param ) 
	{ 
		if( (*(int*)param) == 1 )
		{
			if( game.m_bLevelFinnished )
			{
				game.processNextLevel();
				return;
			}
			commandsActivity[COMMAND_ATTACK] = 1;
			weaponManager.pulse( true );
		}
		else
			commandsActivity[COMMAND_ATTACK] = 0;
	}
}

/** @param param Parameter ukazujici na hodnotu typu int, kde 1 znamena aktivovano a 0 deaktivovano. */
void weapon_manager::attack2( void *param )
{
	if( param ) 
	{ 
		if( (*(int*)param) == 1 )
		{
			commandsActivity[COMMAND_ATTACK2] = 1;
			weaponManager.pulse( true );
		}
		else
			commandsActivity[COMMAND_ATTACK2] = 0;
	}
}

/** @param param Parameter ukazujici na hodnotu typu int, kde 1 znamena aktivovano a 0 deaktivovano. */
void weapon_manager::reload( void *param )
{
	if( param ) 
	{ 
		if( (*(int*)param) == 1 )
		{
			commandsActivity[COMMAND_RELOAD] = 1;
			weaponManager.pulse( true );
		}
		else
			commandsActivity[COMMAND_RELOAD] = 0;
	}
}

/** @return Ukazatel na aktivni zbran. */
BasicWeapon *CWeaponManager::getCurrentWeaponPointer()
{
	if( game.m_pPlayer )
		return game.m_pPlayer->AmmoAndWeapons.getWeapon( m_uiCurrentWeapon );
	return NULL;
}

/** @param pulse True znamena, ze jde o spusteni prikazu, false je opakovani prikazu. */
void CWeaponManager::pulse( bool pulse )
{
	BasicWeapon *pWeapon = getCurrentWeaponPointer();
	if( pWeapon )
	{
		if( commandsActivity[COMMAND_ATTACK] )
			pWeapon->weapon_primaryAttack( pulse );
		else if( commandsActivity[COMMAND_ATTACK2] )
			pWeapon->weapon_secondaryAttack( pulse );
		else if( commandsActivity[COMMAND_RELOAD] )
			pWeapon->weapon_reload( pulse );
	}
}



/**************************************
*	WEAPON MANAGER CLASS
**************************************/


CWeaponManager::CWeaponManager()
{
	reset();
}


void CWeaponManager::reset()
{
	memset( commandsActivity, 0, sizeof( commandsActivity ) );
	m_uiCurrentWeapon = NO_WEAPON;
	m_fHorizontalDeflection = m_fVerticalDeflection = 0;
	m_bDeflecting = false;
	aH = 0;
}

void CWeaponManager::removeAllWeapons()
{
	if( game.m_pPlayer )
	{
		for( int i = WPN_KNIFE; i < WEAPONS_COUNT; ++i )
		{
			BasicWeapon *pWeapon_new = game.m_pPlayer->AmmoAndWeapons.getWeapon( i );
			if( pWeapon_new )
				pWeapon_new->setOwned( false );
		}
		setWeapon( NO_WEAPON );
	}

}


/** @param weaponId Identifikacni cislo zbrane, kterou chceme nastavit jako aktivni. */
void CWeaponManager::setWeapon( unsigned int weaponId )
{
	if( weaponId == 0xFFFFFFFF )	//neni chyba
		weaponId = WEAPONS_COUNT-1;
	weaponId %= WEAPONS_COUNT;
	if( weaponId != m_uiCurrentWeapon )
	{
		if( game.m_pPlayer )
		{
			BasicWeapon *pWeapon_new = game.m_pPlayer->AmmoAndWeapons.getWeapon( weaponId );
			if( pWeapon_new && pWeapon_new->isOwned() )
			{
				BasicWeapon *pWeapon = getCurrentWeaponPointer();
				if( pWeapon && pWeapon_new != pWeapon )
				{
					pWeapon->weapon_holster();
					pWeapon_new->weapon_grab();


					m_uiCurrentWeapon = weaponId;
				}
			}
			
		}
	}
}


void CWeaponManager::run()
{
	//if( m_bWaitForHolster && game.m_pPlayer && m_uiLastWeapon != m_uiCurrentWeapon )
	//{
	//	BasicWeapon *pWeapon_last = game.m_pPlayer->AmmoAndWeapons.getWeapon( m_uiLastWeapon );
	//	if( pWeapon_last )
	//	{
	//		if( pWeapon_last->getLockType() == UNLOCKED )	//holster dokoncen
	//		{
	//			BasicWeapon *pWeapon = game.m_pPlayer->AmmoAndWeapons.getWeapon( m_uiCurrentWeapon );
	//			if( pWeapon )
	//			{
	//				pWeapon->grab();
	//				m_uiLastWeapon = m_uiCurrentWeapon;
	//			}
	//		}
	//	}
	//
	//}
	
	if( !game.m_pPlayer )
		return;

	BasicWeapon *pWeapon = game.m_pPlayer->AmmoAndWeapons.getWeapon( m_uiCurrentWeapon );
	if( pWeapon )
	{
		game.m_iCurrentCrosshair = pWeapon->getCrosshairType();
	}

	if( true || !m_bDeflecting )
	{
		m_fHorizontalDeflection += aH;
		aH = 0.0f;
		if( m_fHorizontalDeflection < 0.0f )
		{
			m_fHorizontalDeflection += getFromRange( max( (m_fHorizontalDeflection*-1.0f) / 2.5f ,0.1f), 0.0f, m_fHorizontalDeflection*-1 );
			
		}
		else if( m_fHorizontalDeflection > 0.0f )
		{
			m_fHorizontalDeflection -= getFromRange( max(m_fHorizontalDeflection / 2.5f,0.1f), 0.0f, m_fHorizontalDeflection );
		}
		
		m_fVerticalDeflection += aV;
		aV = 0.0f;
		if( m_fVerticalDeflection < 0.0f )
		{
			m_fVerticalDeflection += getFromRange( max( (m_fVerticalDeflection*-1.0f) / 2.5f ,0.1f), 0.0f, m_fVerticalDeflection*-1 );
			
		}
		else if( m_fVerticalDeflection > 0.0f )
		{
			m_fVerticalDeflection -= getFromRange( max(m_fVerticalDeflection / 2.5f,0.1f), 0.0f, m_fVerticalDeflection );
		}


		m_WeaponInterpolation.update( 0, m_fHorizontalDeflection, m_fVerticalDeflection );
	}
	else m_bDeflecting = false;

	pulse(false);
}

/** @param deflection Posun v horizontalni rovine. */
void CWeaponManager::addHDeflection(float deflection)
{
	aH = getFromRange( aH + deflection*0.005f, -H_DEFLECTION_MAX, H_DEFLECTION_MAX );
	m_bDeflecting = true;
}

/** @param deflection Posun ve vertikalni rovine. */
void CWeaponManager::addVDeflection(float deflection)
{
	aV = getFromRange( aV + deflection*0.005f, -V_DEFLECTION_MAX, V_DEFLECTION_MAX );
	m_bDeflecting = true;
}

void CWeaponManager::draw()
{
	if( game.m_pPlayer )
	{
		BasicWeapon *pWeapon = game.m_pPlayer->AmmoAndWeapons.getWeapon( m_uiCurrentWeapon );
		if( pWeapon )
		{
			glPushMatrix();



			glRotatef(90,0,1,0);
			glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
			glTranslatef( -4.3f,0,-1);
			glDisable( GL_CULL_FACE );
			glEnable( GL_DEPTH_TEST );
			glEnable( GL_TEXTURE_2D );
			glClear( GL_DEPTH_BUFFER_BIT );
						
			glTranslatef( 0.0f, m_WeaponInterpolation.current.y, m_WeaponInterpolation.current.z );

			pWeapon->draw();
			m_WeaponInterpolation.drawRun(0.5f);


			glPopMatrix();
		}
	}
}
