/*
	This file is part of Warzone 2100.
	Copyright (C) 1999-2004  Eidos Interactive
	Copyright (C) 2005-2007  Warzone Resurrection Project

	Warzone 2100 is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	Warzone 2100 is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Warzone 2100; if not, write to the Free Software
	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/***************************************************************************/
/*
 * Aud.c
 *
 * Warzone audio wrapper functions
 *
 * Gareth Jones 16/12/97
 */
/***************************************************************************/

#include "lib/framework/frame.h"
#include "base.h"
#include "map.h"
#include "disp2d.h"
#include "display3d.h"
#include "lib/ivis_common/piedef.h"
#include "lib/gamelib/gtime.h"

#include "cluster.h"
#include "lib/sound/aud.h"
#include "audio_id.h"

/***************************************************************************/

extern BOOL		display3D;
extern UDWORD	mapX;
extern UDWORD	mapY;
extern iView	player;
extern UDWORD	distance;

/* Map Position of top right hand corner of the screen */
extern UDWORD	viewX;
extern UDWORD	viewY;

/***************************************************************************/

BOOL
audio_ObjectDead( void * psObj )
{
	SIMPLE_OBJECT	*psSimpleObj = (SIMPLE_OBJECT *) psObj;
	BASE_OBJECT		*psBaseObj;
	PROJ_OBJECT		*psProj;

	/* check is valid simple object pointer */
	if ( !PTRVALID(psSimpleObj, sizeof(SIMPLE_OBJECT)) )
	{
		debug( LOG_NEVER, "audio_ObjectDead: simple object pointer invalid\n" );
		return TRUE;
	}

	/* check projectiles */
	if ( psSimpleObj->type == OBJ_BULLET )
	{
		psProj = (PROJ_OBJECT *) psSimpleObj;
		if ( !PTRVALID(psProj, sizeof(PROJ_OBJECT)) )
		{
			debug( LOG_NEVER, "audio_ObjectDead: projectile object pointer invalid\n" );
			return TRUE;
		}
		else
		{
			if ( psProj->state == PROJ_POSTIMPACT )
			{
				return TRUE;
			}
			else
			{
				return FALSE;
			}
		}
	}
	else
	{
		/* check base object */
		psBaseObj = (BASE_OBJECT *) psObj;

		/* check is valid pointer */
		if ( !PTRVALID(psBaseObj, sizeof(BASE_OBJECT)) )
		{
			debug( LOG_NEVER, "audio_ObjectDead: base object pointer invalid\n" );
			return TRUE;
		}
		else
		{
			return psBaseObj->died;
		}
	}
}

/***************************************************************************/

void
audio_Get2DPlayerPos( SDWORD *piX, SDWORD *piY, SDWORD *piZ )
{
	*piX = mapX << TILE_SHIFT;
	*piY = mapY << TILE_SHIFT;
	*piZ = 0;
}

/***************************************************************************/

void
audio_Get3DPlayerPos( SDWORD *piX, SDWORD *piY, SDWORD *piZ )
{
	/* player's y and z interchanged */
	*piX = player.p.x + ((visibleXTiles/2) << TILE_SHIFT);
	*piY = player.p.z + ((visibleYTiles/2) << TILE_SHIFT);
	*piZ = player.p.y;

	/* invert y to match QSOUND axes */
	*piY = (GetHeightOfMap() << TILE_SHIFT) - *piY;
}

/***************************************************************************/
/*
 * get player direction vector - always 0 in 2D
 */
/***************************************************************************/

void
audio_Get2DPlayerRotAboutVerticalAxis( SDWORD *piA )
{
	*piA = (SWORD) 0;
}

/***************************************************************************/
/*
 * get player direction vector - angle about vertical (y) ivis axis
 */
/***************************************************************************/

void
audio_Get3DPlayerRotAboutVerticalAxis( SDWORD *piA )
{
	*piA = player.r.y / DEG_1;
}

/***************************************************************************/

BOOL
audio_Display3D( void )
{
	return display3D;
}

/***************************************************************************/
/*
 * audio_GetStaticPos
 *
 * Get QSound axial position from world (x,y)
 */
/***************************************************************************/

void
audio_GetStaticPos( SDWORD iWorldX, SDWORD iWorldY,
					SDWORD *piX, SDWORD *piY, SDWORD *piZ )
{
	*piX = iWorldX;
	*piZ = map_TileHeight( iWorldX >> TILE_SHIFT,
						   iWorldY >> TILE_SHIFT );
	/* invert y to match QSOUND axes */
	*piY = (GetHeightOfMap() << TILE_SHIFT) - iWorldY;
}

/***************************************************************************/

void
audio_GetObjectPos( void *psObj, SDWORD *piX, SDWORD *piY, SDWORD *piZ )
{
	BASE_OBJECT	*psBaseObj = (BASE_OBJECT *) psObj;

	/* check is valid pointer */
	ASSERT( PTRVALID(psBaseObj, sizeof(BASE_OBJECT)),
			"audio_GetObjectPos: game object pointer invalid\n" );

	*piX = psBaseObj->x;
	*piZ = map_TileHeight( psBaseObj->x >> TILE_SHIFT,
						   psBaseObj->y >> TILE_SHIFT );

	/* invert y to match QSOUND axes */
	*piY = (GetHeightOfMap() << TILE_SHIFT) - psBaseObj->y;
}

/***************************************************************************/

UWORD
audio_GetScreenWidth( void )
{
	return (UWORD) DISP_WIDTH;
}

/***************************************************************************/
/*
 * audio_GetClusterCentre
 *
 * returns FALSE if no droids moving
 */
/***************************************************************************/

BOOL
audio_GetClusterCentre( void *psClusterObj, SDWORD *piX, SDWORD *piY, SDWORD *piZ )
{
	SDWORD	iClusterID, iNumObj;
	DROID	*psDroid = (DROID *) psClusterObj;
	BOOL	bDroidInClusterMoving = FALSE;

	/* check valid pointer */
	ASSERT( PTRVALID(psDroid, sizeof(DROID)),
			"audio_GetClusterCentre: game object pointer invalid\n" );

	iNumObj = *piX = *piY = *piZ = 0;

	/* clustGetClusterID returns 0 if cluster is empty or no droids moving */
	iClusterID = clustGetClusterID( psClusterObj );
	if ( iClusterID == 0 )
	{
		debug( LOG_NEVER, "audio_GetClusterCentre: empty cluster!\n" );
		return FALSE;
	}
	else
	{
		clustInitIterate( iClusterID );
		do
		{
			psDroid = (DROID *) clustIterate();
			if ( psDroid != NULL && psDroid->sMove.Status != MOVEINACTIVE )
			{
				iNumObj++;
				*piX += psDroid->x;
				*piY += psDroid->y;
				*piZ += psDroid->z;
				bDroidInClusterMoving = TRUE;
			}
		}
		while ( psDroid != NULL );

		/* get average */
		if ( bDroidInClusterMoving == TRUE )
		{
			*piX /= iNumObj;
			*piY /= iNumObj;
			*piZ /= iNumObj;

			/* invert y to match QSOUND axes */
			*piY = (GetHeightOfMap() << TILE_SHIFT) - *piY;
		}
	}

	return bDroidInClusterMoving;
}

/***************************************************************************/
/*
 * audio_GetNewClusterObject
 *
 * get next droid in cluster if current object dead
 */
/***************************************************************************/

BOOL
audio_GetNewClusterObject( void **psClusterObj, SDWORD iClusterID )
{
	DROID	*psDroid = (DROID *) *psClusterObj;

	/* check valid pointer */
	ASSERT( PTRVALID(psDroid, sizeof(DROID)),
			"audio_GetNewClusterObject: game object pointer invalid\n" );

	/* return if droid not dead */
	if ( !psDroid->died )
	{
		return FALSE;
	}

	if ( iClusterID == 0 )
	{
		debug( LOG_NEVER, "audio_GetNewClusterObject: empty cluster!\n" );
		return FALSE;;
	}
	else
	{
		/* find next undying droid in cluster */
		clustInitIterate( iClusterID );
		do
		{
			psDroid = (DROID *) clustIterate();
			if ( psDroid != NULL && !psDroid->died )
			{
				*psClusterObj = psDroid;
				return TRUE;
			}
		}
		while ( psDroid != NULL );
	}

	return FALSE;
}

/***************************************************************************/

BOOL
audio_ClusterEmpty( void * psClusterObj )
{
	/* clustGetClusterID returns 0 if cluster is empty */
	if ( clustGetClusterID( psClusterObj ) == 0 )
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

/***************************************************************************/

SDWORD
audio_GetClusterIDFromObj( void *psClusterObj )
{
	return clustGetClusterID( psClusterObj );
}

/***************************************************************************/

BOOL
audio_GetIDFromStr( STRING *pWavStr, SDWORD *piID )
{
	return audioID_GetIDFromStr( pWavStr, piID );
}

/***************************************************************************/

UDWORD
sound_GetGameTime( void )
{
	return gameTime;
}

/***************************************************************************/
