/*********************************************************************//**
*	Dvere.
*	Dvere se pohybuji mezi dvema body.
*	
*	author: Michal Jirous
*	date: 23.04.2009
*	file: ent_func_door.cpp
**********************************************************************/

#include "ent_func_door.h"

FuncDoor::FuncDoor() : CBaseMoveable()
{
	m_bIsOpenedOrOpening = false;
	m_iDamage = 0;
	m_bTargetOnly = false;
	m_bUseOnly = false;
	m_bToggle = false;
	m_bStartOpen = false;
	m_sClassName = "func_door";
	m_iProperties = ENT_PARM_COLLIDING | ENT_PARM_FORCE_MOVING | ENT_PARM_INTERACTIVE | ENT_PARM_POINTING | ENT_PARM_RENDER | ENT_PARM_RUNNABLE | ENT_PARM_SHOOTABLE;
	m_uiResetDelay = TRIGGER_INFINITE;
	m_uiResetTime = TRIGGER_INFINITE;
	m_bActivated = false;
	m_fVolume = 1.0f;
}

void FuncDoor::passFlags( int flags )
{
	if( flags & DOOR_STARTS_OPEN )
		m_bStartOpen = true;
	if( flags & DOOR_TARGET_ONLY )
		m_bTargetOnly = true;
	if( flags & DOOR_TOGGLE )
		m_bToggle = true;
	if( flags & DOOR_USE_ONLY )
		m_bUseOnly = true;
}


void FuncDoor::setParameters( parameters_t &parametersMap )
{
	CBaseMoveable::setParameters( parametersMap );
	std::string value = getParameterValue( parametersMap, "speed" );
	float fSpeed = 1.0f;
	if( !value.empty() )
		fSpeed = (float)atof( value.c_str() );

	float fDistance = 0.0f;
	value = getParameterValue( parametersMap, "distance" );
	if( !value.empty() )
		fDistance = (float)atof( value.c_str() );

	value = getParameterValue( parametersMap, "damage" );
	if( !value.empty() )
		m_iDamage = atoi( value.c_str() );

	value = getParameterValue( parametersMap, "wait" );
	if( !value.empty() )
		m_uiResetDelay = atoi( value.c_str() );

	value = getParameterValue( parametersMap, "volume" );
	if( !value.empty() )
		m_fVolume = (float)atof( value.c_str() );
	


	value = getParameterValue( parametersMap, "lockedsound" );
	int lock = 0;
	if( !value.empty() )
	{
		lock = atoi( value.c_str() );
	}
	
	if( m_bTargetOnly && lock != -1 )
	{
		generalSounds.setLockSound( lock, m_LockedSound );
		m_LockedSound.setPosition( origin.x, origin.y, origin.z );
	}

	value = getParameterValue( parametersMap, "movesnd" );
	int sound = 0;
	if( !value.empty() )
		sound = atoi( value.c_str() );

	if( sound > 0 && sound <= MOVE_SOUNDS_COUNT )
		m_MySoundPool.addSound( MOVE_SOUNDS[sound-1], MOVE_SOUND );


	

	value = getParameterValue( parametersMap, "stopsnd" );
	sound = 0;
	if( !value.empty() )
		sound = atoi( value.c_str() );

	if( sound > 0 && sound <= STOP_SOUNDS_COUNT )
		m_MySoundPool.addSound( STOP_SOUNDS[sound-1], STOP_SOUND );


	m_LockedSound.setGain( m_fVolume );
	m_MySound.setGain( m_fVolume );

	Vector movement;
	movement.createFrom2Angles( -angles[0], angles[2] );
	movement = movement * fDistance;

	m_Target = origin + movement;
	setVelocity( fSpeed );
}

void FuncDoor::restart()
{
	m_uiResetTime = TRIGGER_INFINITE;
	m_bActivated = false;
	m_bIsOpenedOrOpening = false;
	setTarget( m_Store_StartOrigin );
	CBaseMoveable::restart();
	m_MySound.setPosition( origin.x, origin.y, origin.z );
	m_MySound.stop();
}



void FuncDoor::compile()
{
	CBaseMoveable::compile();

	if( m_bStartOpen )	//switch start and target
	{
		Vector translation( m_Target - origin );

		(*m_pSortBoundingBox).translate( translation );	//posuneme bounding box
		Point tmp = origin;
		origin = m_Target;
		m_Target = tmp;
		m_bIsOpenedOrOpening = true;

		m_Store_StartOrigin = origin;
		m_Store_Target = m_Target;

	}


	
	
	setTarget( origin );	//no move on start
	
	m_MySound.setSourceRelative( AL_FALSE );
	m_MySound.setPosition( origin.x, origin.y, origin.z );
}

void FuncDoor::onTarget( int target_type )
{
	if( (m_bToggle || !m_bActivated && !m_bToggle) && !m_bUseOnly )
		switchDirection();	//no storage
}

void FuncDoor::onUsage( const RayTraceData &rayData )
{
	if( (m_bToggle || !m_bActivated && !m_bToggle) && !m_bTargetOnly )
		switchDirectionStore();
}

void FuncDoor::onCollide( CollisionData &collData )
{
	if( m_bTargetOnly && !m_bActivated )
		m_LockedSound.playIfNotPlaying();

	if( (!m_bActivated ) && !m_bTargetOnly && !m_bUseOnly )
		switchDirectionStore();
}

void FuncDoor::onReachTarget()
{
	m_MySound.stop();
	m_MySound.setLooping( AL_FALSE );
	m_MySoundPool.use( STOP_SOUND, m_MySound );
	m_MySound.play();
}

void FuncDoor::onStartMoving()
{
	m_MySound.stop();
	m_MySoundPool.use( MOVE_SOUND, m_MySound );
	m_MySound.setLooping( AL_TRUE );
	m_MySound.play();
}


#include "game.h"
void FuncDoor::switchDirection()
{
	if( m_bActivated )
	{
		m_BackTimeData.push_front( BackTimeData() );
		m_BackTimeData.front().event_time = game.getGameTime();
		m_BackTimeData.front().type = EVENT_CLOSE;
	}
	else
	{
		m_BackTimeData.push_front( BackTimeData() );
		m_BackTimeData.front().event_time = game.getGameTime();
		m_BackTimeData.front().type = EVENT_OPEN;
	}

	m_bActivated ^= 1;
	if( m_bActivated == true && !m_bToggle && m_uiResetDelay != TRIGGER_INFINITE )	//provedeme reset
	{
		m_uiResetTime = game.getGameTime();
	}

	if( m_bActivated == true )
		setTarget( m_Store_Target );
	else
		setTarget( m_Store_StartOrigin );

	m_bIsOpenedOrOpening = m_bStartOpen ^ m_bActivated;
}



void FuncDoor::switchDirectionStore()
{
	m_BackTimeData.push_front( BackTimeData() );
	m_BackTimeData.front().event_time = game.getGameTime();
	m_BackTimeData.front().type = EVENT_TRIGGER;

	switchDirection();
}

void FuncDoor::update( float seconds )
{
	CBaseMoveable::update( seconds );
	if( m_bActivated && !m_bToggle )
	{
		if( m_uiResetDelay != TRIGGER_INFINITE && m_uiResetTime != TRIGGER_INFINITE )
		{
			if( m_uiResetDelay + m_uiResetTime < game.getGameTime() )
			{
				switchDirectionStore();			
			}
		}
	}

	m_MySound.setPosition( origin.x, origin.y, origin.z );
}

void FuncDoor::passStoredEvent( BackTimeData &backData )
{
	CBaseMoveable::passStoredEvent( backData );

	//je jedno jaky...protoze ve spravnym poradi je to vzdy switch
	if( backData.type == EVENT_TRIGGER )
		switchDirectionStore();
}

void FuncDoor::goBackInTime()
{
	CBaseMoveable::goBackInTime();
	//potrebujeme najit v jakym stavu system byl
	for( std::list<BackTimeData>::reverse_iterator riter = m_BackTimeData.rbegin(); riter != m_BackTimeData.rend(); ++riter )
	{
		if( (*riter).type == EVENT_BORDER )	//na border bych tu nemel narazit
			return;

		if( (*riter).type == EVENT_OPEN )
		{
			m_bActivated = false;
			m_bIsOpenedOrOpening = m_bStartOpen;
			return;
		}
		else if( (*riter).type == EVENT_CLOSE )
		{
			m_bActivated = true;
			m_bIsOpenedOrOpening = m_bStartOpen ^ 1;
			return;
		}

	}


}

void FuncDoor::blockMovement( CollisionData &collData )
{
	switchDirectionStore();
}

void FuncDoor::decompile()
{
	soundLibrary.unloadSound( m_LockedSound );
	m_MySound.stop();
	m_MySoundPool.destroy();
}
