// Author : Chris Tolley
// Date   : 8/25/2004
// carcus.cpp contains the class definition for a class that will act as
// a carcus for dead bugs in the game Survival

#include <windows.h>
#include <gl/gl.h>
#include <math.h>

#include "carcus.h"
#include "Bug.h"
#include "viewFrustum.h"
#include "logger.h"

// Some constants to help us out
// The life time of a carcus in seconds
const float		DECOMPISITION_TIME = 10;

// Constructor  bug is the bug that this carcus looks like
carcus::carcus( SmartPointer& bug )
: m_fAge( 0 ), m_uiList( 0 )
{
	// Make sure that bug is valid
	if( ! bug.isValid() )
	{
		logger::event( "carcus::Constructor", "Invalid pointer", 0 );
		return;
	}// End if

	// Get a pointer to the bug
	Bug* pBug = reinterpret_cast< Bug* >( bug.Get() );

	// Set up the display list based on the display list of the bug
	m_uiList = pBug->GetListId();

	// Set up the matrix to the same as the bug's matrix
	m_mLocal = *( pBug->GetCoordSystem() );
}// End carcus::Constructor


// Destructor
carcus::~carcus()
{}


// Updates the object.  Must be implemented at a derived level
void carcus::Update( float elapsedSec )
{
	// Update the age of this carcus
	m_fAge += elapsedSec;
}// End carcus::Update


// Renders the object to the screen. Must be implemented at a derived level
void carcus::Render()
{
	// Get the position of this carcus
	float mx, my, mz;
	GetPos( mx, my, mz );

	// If this carcus is in the view frustum we should draw it.
	if( viewFrustum::sphereInFrustum( mx, my, mz, mx + BUG_RADIUS, my, mz ) )
	{
		// Set up the local matrix system
		glPushMatrix();
		glMultMatrixf( m_mLocal.get() );

		// Enable blending
		glEnable( GL_BLEND );

		// Set the transparency up
		glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

		// Set up the alpha value based on the age of this carcus
		glColor4f( 1, 1, 1, 1 - ( m_fAge / DECOMPISITION_TIME ) );

		// Call the display list containing the commands to draw the carcus
		glCallList( m_uiList );

		// Reset the color
		glColor4f( 1, 1, 1, 1 );

		// Disable blending
		glDisable( GL_BLEND );
		
		// Reset the matrix stack
		glPopMatrix();
	}// End if
}// End carcus::Render


// Returns true if this Object is inside the sphere
bool carcus::InSphere( float x, float z, float radius )
{
	// Get the center point of this carcus
	float bx, by, bz;
	GetPos( bx, by, bz );

	// Calculate the distance between this carcus and point x,z
	float distance = sqrt( ( ( x - bx ) * ( x - bx ) ) +
						   ( ( z - bz ) * ( z - bz ) ) );

	// If the distance between this carcus and x,z is less than radius
	// plus this of this bug, then it is in the sphere
	return distance <= ( radius +  BUG_RADIUS );
}// End carcus::InSphere


// Returns true if it is time for this object to be removed
bool carcus::TimeToDie()
{
	return m_fAge >= DECOMPISITION_TIME;
}// End carcus::TimeToDie