///////////////////////////////////////////////////////////////////////////////
//
// File      : Asura_PS3_ReplaceableSounds.cpp
// Author    : Philip Hall
// Created   : 17/09/2007
//
// Copyright (C) 2007 Rebellion. All Rights Reserved
//
///////////////////////////////////////////////////////////////////////////////

#include "Core/Asura.h"

#ifndef ASURA_USE_AUDIO_SYSTEM

// Asura headers
#include "Core/Asura_String.h"
#include "Core/Memory/Asura_Mem.h"
#include "Debugging/Asura_Assert.h"
#include "Debugging/Asura_Logfile.h"
#include "FileAccess/Asura_FileAccess.h"
#include "Sound/Asura_Sound.h"

// Asura PS3 headers
#include "Sound/Asura_PS3_Sound_System.h"

// This file's header
#include "Sound/Asura_PS3_ReplaceableSounds.h"


// S T A T I C   C L A S S   D A T A /////////////////////////////////////////
Asura_PS3_ReplaceableSound_System Asura_PS3_ReplaceableSound_System::s_xAPI;


Asura_PS3_ReplaceableSound::Asura_PS3_ReplaceableSound()
{
	m_uByteOffset = ASURA_PS3_SOUND_INVALID_BYTE_OFFSET;
	m_uSoundSize = 0;
	m_bLoaded = false;
}



////PGH////////////////////////////////////////////////////////////////////////
// Function    : Asura_PS3_ReplaceableSound_System::Asura_PS3_ReplaceableSound_System
// Description : Replaceable Sound constructor - initialises to known defaults
//
// Parameters  : none
//
// Returns     : nothing
///////////////////////////////////////////////////////////////////////////////
Asura_PS3_ReplaceableSound_System::Asura_PS3_ReplaceableSound_System()
{
	m_szReplaceableSoundFile[0] = 0;
}


////PGH////////////////////////////////////////////////////////////////////////
// Function    : Asura_PS3_ReplaceableSound_System::Initialise
// Description : Initialise the replaceable sound subsystem
//
// Parameters  : 
//   const char* szFilename - Replaceable sounds source file
//
// Returns     : bool - Returns true on success
///////////////////////////////////////////////////////////////////////////////
bool Asura_PS3_ReplaceableSound_System::Initialise( const char* szFilename )
{
	Asura_PrintfToBfr( m_szReplaceableSoundFile, "%s", ASURA_PS3_MAX_PATH - 1, true, szFilename );

	return true;
}


////PGH////////////////////////////////////////////////////////////////////////
// Function    : Asura_PS3_ReplaceableSound_System::Shutdown
// Description : Shutdown and free memory from the replaceable sound subsystem
//
// Parameters  : none
//
// Returns     : nothing
///////////////////////////////////////////////////////////////////////////////
void Asura_PS3_ReplaceableSound_System::Shutdown()
{
	for ( u_int u = 0; u < ASURA_MAX_NUMBER_OF_LOADED_SOUNDS; ++u )
	{
		if ( m_axReplaceableSounds[u].IsLoaded() )
		{
			Asura_PS3_Sound_System::GetAPI().UnloadSound( u );
			m_axReplaceableSounds[u].SetLoaded(false);
		}
	}
}


void Asura_PS3_ReplaceableSound_System::Reset()
{
	// Some bizzarre behaviour copied from the PC implementation
	for ( u_int u = 0; u < ASURA_MAX_NUMBER_OF_LOADED_SOUNDS; ++u )
	{
		if ( m_axReplaceableSounds[u].IsLoaded() )
		{
			Asura_PS3_Sound_System::GetAPI().UnloadSound( u );
			m_axReplaceableSounds[u].SetLoaded(false);
		}
	}
}


////PGH////////////////////////////////////////////////////////////////////////
// Function    : Asura_PS3_ReplaceableSound_System::LoadReplaceableSound
// Description : Load a replaceable sound from the file (taken from PC source)
//
// Parameters  : 
//   int iLoadedSoundID - Index of existing loaded sound
//
// Returns     : bool - Returns true on success
///////////////////////////////////////////////////////////////////////////////
bool Asura_PS3_ReplaceableSound_System::LoadReplaceableSound( int iLoadedSoundID )
{
	if ( (iLoadedSoundID < 0) || (iLoadedSoundID >= ASURA_MAX_NUMBER_OF_LOADED_SOUNDS) )
	{
		Asura_Assert(false, "Loaded sound index out of range");
		return false;
	}

	Asura_PS3_ReplaceableSound& xSound = m_axReplaceableSounds[iLoadedSoundID];

	// Ignore load request if already loaded
	if ( xSound.IsLoaded() ) { return true; }

	// Sound must be valid ( i.e. initialised with offset & size)
	if ( !xSound.IsValid() )
	{
		Asura_Assert( false, "Replaceable sound is invalid." );
		return false;
	}

	// Load sound file
	Asura_Handle iFileHandle = Asura_FileAccess::Open( m_szReplaceableSoundFile );
	if ( iFileHandle == ASURA_INVALID_HANDLE )
	{
		Asura_Assert( false, "Failed to open file for replaceable sound." );			
		return false;
	}

	// Skip past the data we don't want
	Asura_FileAccess::SkipData( iFileHandle, xSound.GetOffset() );

	bool bOK = Asura_PS3_Sound_System::GetAPI().LoadSoundFromResource( iFileHandle, xSound.GetSize(), iLoadedSoundID );
	if ( bOK )
	{
		m_axReplaceableSounds[iLoadedSoundID].SetLoaded(true);
	}

	Asura_FileAccess::Close( iFileHandle );
	return bOK;
}


////PGH////////////////////////////////////////////////////////////////////////
// Function    : Asura_PS3_ReplaceableSound_System::ReplaceSound
// Description : Replace an existing sound with another one
//
// Parameters  : 
//	int iExistingSoundLoadedID  - Existing sound
//	int iNewSoundLoadedID       - New sound
//
// Returns     : bool - Returns true on success
///////////////////////////////////////////////////////////////////////////////
bool Asura_PS3_ReplaceableSound_System::ReplaceSound( int iExistingSoundLoadedID, int iNewSoundLoadedID )
{
	// moved here from Asura_PCSound_System::ReplaceSound()
	Asura_Assert( m_axReplaceableSounds[iExistingSoundLoadedID].IsLoaded(), "Replaced sound not in memory." );
	Asura_Assert( !m_axReplaceableSounds[iNewSoundLoadedID].IsLoaded(), "Sound to replace is already in memory." );

	if ( !m_axReplaceableSounds[iNewSoundLoadedID].IsValid() )
	{
		Asura_Assert( 0, "Invalid replaceable sound." );
		return false;
	}

	bool bOK = Asura_PS3_Sound_System::GetAPI().UnloadSound( iExistingSoundLoadedID );
	if ( bOK )
	{
		m_axReplaceableSounds[iExistingSoundLoadedID].SetLoaded(false);
		bOK = LoadReplaceableSound( iNewSoundLoadedID );
	}

	return bOK;
}


////PGH////////////////////////////////////////////////////////////////////////
// Function    : Asura_PS3_ReplaceableSound_System::AddReplaceableSoundInfo
// Description : Adds information about a replaceable sound
//
// Parameters  : 
//   int iSoundId        - Actual sound ID (as used in game code)
//   u_int uiByteOffset  - Byte offset into the source file
//   u_int uiSize        - Size of sound (bytes)
//
// Returns     : bool - Returns true on success
///////////////////////////////////////////////////////////////////////////////
bool Asura_PS3_ReplaceableSound_System::AddReplaceableSoundInfo( int iSoundId, u_int uiByteOffset, u_int uiSize )
{
	if ( uiSize == 0 )
	{
		Asura_Assert(false, "Replaceable sound must have a nonzero size")
		return false;
	}

	int iLoadedIndex = Asura_Sound_System::SoundLoadedByPlatformCode( static_cast<Asura_Sound_ID>( iSoundId ) );

	// Probably already loaded
	if ( iLoadedIndex == ASURA_INVALID_LOADED_SOUND_INDEX )
	{
		return false;
	}

	m_axReplaceableSounds[iLoadedIndex].Create(uiByteOffset, uiSize);
	return true;
}

#endif // #ifndef ASURA_USE_AUDIO_SYSTEM

//eof
