/*********************************************************************//**
*	Definice veci
*	Soubor definuje abstraktni tridu vsech veci a dale konkretni zbrane
*	a veci.
*	
*	author: Michal Jirous
*	date: 23.04.2009
*	file: ent_items.cpp
**********************************************************************/

#include "ent_items.h"
#include "game.h"

CBaseItem::CBaseItem( ) : CBaseDetail()
{
	m_bIsDeath = false;
	m_pModel = NULL;
	//m_sModelFilename = "";
	//m_sSoundFilename = "";
	m_iProperties = ENT_PARM_COLLIDING | ENT_PARM_RUNNABLE | ENT_PARM_RENDER;
	m_pSortBoundingBox = &m_RenderBounds;
	m_pNearestFace = NULL;
}

void CBaseItem::render( RenderData &renderData )
{
	if(!m_bIsDeath)
	{

			glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT );
			
			glDisable(GL_LIGHTING);
			glFrontFace(GL_CCW);
			
			glPushMatrix();

			glEnable( GL_BLEND );
			glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

			glTranslatef(origin[0],origin[1],origin[2]);
			
			if( m_pNearestFace )
				glColor4f( rendercolor[0], rendercolor[1], rendercolor[2], m_Alpha / 255.0f );
			else
				glColor4f(1,1,1,1);

			if(m_pModel)
			{
				m_pModel->update( renderData.frameTimes.elapsed_seconds );
				m_pModel->draw();
			}

			glPopMatrix();
			
			glFrontFace(GL_CW);
			glPopAttrib();

	}

}

bool CBaseItem::renderCullTest( RenderData &renderData )
{
	if( !m_bIsDeath && renderData.frustum->isBoundsInsideFrustum( m_RenderBounds ) )
	{
		return CBaseDetail::renderCullTest( renderData );
	}
	return false;
}


using namespace modelLib;
#include "level_collision.h"
void CBaseItem::compile()
{	
	CBaseDetail::compile();
	//TODO get bounding box from model!!!
	


	m_CollisionBounds.setBasicValues( Point(origin[0] - DEFAULT_ITEM_SIZE, origin[1] - DEFAULT_ITEM_SIZE, origin[2] ) );
	m_CollisionBounds.updateData( Point(origin[0] + DEFAULT_ITEM_SIZE, origin[1] + DEFAULT_ITEM_SIZE, origin[2] + 2.0f * DEFAULT_ITEM_SIZE ) );

	//TODO get bounding box from model!!!
	//m_RenderBounds.setBasicValues( Point(origin[0] - DEFAULT_ITEM_SIZE_RENDER, origin[1] - DEFAULT_ITEM_SIZE_RENDER, origin[2] ) );
	//m_RenderBounds.updateData( Point(origin[0] + DEFAULT_ITEM_SIZE_RENDER, origin[1] + DEFAULT_ITEM_SIZE_RENDER, origin[2] + 2.0f * DEFAULT_ITEM_SIZE_RENDER ) );

	soundLibrary.loadSound( m_Sound, m_sSoundFilename );
	m_Sound.setPosition( origin.x, origin.y, origin.z );

	//todo - coz takhle univerzalni funkci pro nacitani modelu se samodetekci typu
	m_pModel = modelLib::modelLibrary.applyHalfLifeMDL(m_sModelFilename);

	m_pModel->getBoundingBox( (float*)m_RenderBounds.m_fBounds, (float*)&m_RenderBounds.m_fBounds[3] );
	m_RenderBounds.translate( origin );


	m_RenderBounds.setRange( 10.0f );
	float distance = 100.0f;
	m_pNearestFace = collisionSystem.findNearestFace( m_RenderBounds, distance );
	m_RenderBounds.setRange( -10.0f );
}

void CBaseItem::decompile()
{
	CBaseDetail::decompile();
	if(m_pModel)
	{
		modelLib::modelLibrary.unloadModel( m_sModelFilename );
		modelLib::modelLibrary.freeModelElement( m_pModel );
	}
	soundLibrary.unloadSound( m_Sound );

}

bool CBaseItem::collisionDetection( CollisionData &collData )
{
	if( !m_bIsDeath && m_CollisionBounds.compare( collData.model.m_DynamicBounds ) )
	{
		CBaseEntity* pEntity = ((CBaseEntity*)collData.initiator);
		if( pEntity->getClassName() == "player" )
		{
			m_bIsDeath = true;
			m_Sound.play();

		
			m_BackTimeData.push_front( BackTimeData() );
			m_BackTimeData.front().event_time = game.getGameTime();
			m_BackTimeData.front().type = EVENT_ITEM_TAKEN;


			give( reinterpret_cast<CPlayer*>(pEntity) );
		}
	}
	return false;
}

void CBaseItem::restart()
{
	CBaseDetail::restart();
	m_bIsDeath = false;
}

void CBaseItem::passStoredEvent( BackTimeData &backData )
{
	CBaseDetail::passStoredEvent( backData );
	if( backData.type == EVENT_ITEM_TAKEN )
		m_bIsDeath = true;

}

void CBaseItem::goBackInTime()
{
	CBaseDetail::goBackInTime();
	//musime zjistit, jestli je tento objekt sebrany nebo ne
	for( std::list<BackTimeData>::reverse_iterator riter = m_BackTimeData.rbegin(); riter != m_BackTimeData.rend(); ++riter )
	{
		if( (*riter).type == EVENT_BORDER )
			return;

		if( (*riter).type == EVENT_ITEM_TAKEN )
		{	
			m_bIsDeath = false;
			return;
		}
	}
}

void CBaseItem::update( float seconds )
{
	CBaseDetail::update( seconds );
	if( m_pNearestFace )
		m_pNearestFace->getLightColor( (GLfloat*)&rendercolor );
}
