/**
*
* \file Asura_Client.cpp
*
* Created by Kevin Lea - 13/08/2002 10:07:29
*
* Copyright (C) 2002 Rebellion, All Rights Reserved.
*
* \brief
*
**/

#include "Core/Asura.h"

#include "Animation/Asura_TextureAnimation.h"
#ifdef ASURA_USE_ATTRACTORS
#include "Attractors/Asura_Attractor_System.h"
#endif
#include "Core/Asura_Timers.h"
#include "Cutscene/Asura_Cutscene_System.h"
#include "Debugging/Asura_Assert.h"
#ifdef ASURA_SUPPORT_COMMAND_CONSOLE_REMOTE
#include "Interface/Asura_CommandConsole_Remote.h"
#endif
#ifdef ASURA_SUPPORT_GAMESPY_VOICE
#include "Network/Asura_GameSpy_Voice.h"
#endif // #ifdef ASURA_SUPPORT_GAMESPY_VOICE
#include "Network/Asura_Network.h"
#include "Network/Asura_Message.h"
#ifdef ASURA_SUPPORT_NETMSG_SYSTEM
#include "Network/Asura_NetMsg.h"
#endif
#ifdef ASURA_SUPPORT_LOBBY
#include "Network/Online/Asura_Lobby.h"
#endif
#ifdef ASURA_USE_DIALOGUE_SYSTEM
#include "Sound/Asura_Dialogue_System.h"
#endif
#ifdef ASURA_SUPPORT_DYNAMIC_MUSIC_SYSTEM
#include "Sound/Asura_Dynamic_Music_System.h"
#endif
#include "Sound/Asura_Sound_Mixer.h"
#include "Sound/Asura_Music.h"
#include "Sound/Asura_MetaMusic_System.h"
#include "Sound/Asura_Sound.h"
#include "Sound/Asura_StreamingBackgroundSound_System.h"
#include "SpecialFX/Asura_Beam_System.h"

#ifdef ASURA_USE_COLLISIONFX
#include "SpecialFX/Asura_CollisionFX_System.h"
#endif //ASURA_USE_COLLISIONFX

#if !defined(ASURA_DONT_USE_TELEPORTERS)
#include "Teleport/Asura_Teleport_System.h"
#endif	// !defined(ASURA_DONT_USE_TELEPORTERS)
#ifdef ASURA_USE_FSFX
#include "FSFX/Asura_FSFX_System.h"
#endif // ASURA_USE_FSFX

#ifdef ASURA_USE_GUI_MENU_SYSTEM
//#include "GUIMenu/Asura_GUIMenu_Message.h"
#include "GUIMenu/Asura_GUIMenu_System.h"
#endif

// C L A S S   F U N C T I O N   I M P L E M E N T A T I O N S ///////////////
void Asura_Network::ClientMessageHandler(const Asura_Message* pxMessage)
{
    if( !Asura_Network::ShouldMessageBeHandledOnClient(pxMessage) ) { return; }

	switch(pxMessage->GetMsgID())
	{
		/// Kevin Lea - 30/01/2002 11:56:14 - internal housekeeping messages
#ifdef ASURA_SUPPORT_NETMSG_SYSTEM
		case ASURA_MSG_NETMSGUPDATE:
		{
			// send messages to client from server
			Asura_NetMsg_System::ProcessSlaveUpdatePackage(reinterpret_cast<const u_char*>(pxMessage->GetData()), static_cast<u_short>(pxMessage->GetDataSize()), pxMessage->GetSentTime());
			break;
		}
#endif//#ifdef ASURA_SUPPORT_NETMSG_SYSTEM

		case ASURA_MSG_VALIDCLIENTGUID:
		{
			const Asura_MsgData_ValidClientGuid* data = reinterpret_cast
				<const Asura_MsgData_ValidClientGuid*>(pxMessage->GetData());
			s_uNextClientGuid = data->Guid;
			s_uInitialClientGuid = data->Guid; // SNH - 02/09/2003 17:18:59 - save this guid, so we can reset s_uNextClientGuid to it when ResetPlayerStatus is called
			s_bReceivedValidClientGuids = true;
			
			// (MH - 22.05.2003) this is always the first message received 
			// by the client so init the global time. Possibly not the best 
			// time to do it since latency might not yet be accurate?
			Asura_Timers::UpdateServerAbsoluteTime(pxMessage->GetSentTime(), GetLatency(), true);
			break;
		}
		
		case ASURA_MSG_CREATE_BEAM:
		{
			Asura_Beam_System::HandleMessage(pxMessage);
			break;
		}

#if !defined(ASURA_SUPPORT_DYNAMIC_MUSIC_SYSTEM)
		case ASURA_MSG_MUSICSYSTEM_PLAY :
		{
			const Asura_MsgData_MusicSystem_Play* pxData = reinterpret_cast
				<const Asura_MsgData_MusicSystem_Play*>(pxMessage->GetData());
			if(pxData->m_ucMusicTrack != Asura_Music_System::GetCurrentTrack())
			{
				if(pxData->m_ucMusicTrack == ASURA_MUSIC_TRACK_NONE)
				{
					Asura_Music_System::Stop(pxData->m_fFadeTime);
				}
				else
				{
					float fVolume = (float)pxData->m_ucVolume / 128.0f;
					Asura_Music_System::Play((Asura_Music_TrackID)pxData->m_ucMusicTrack,
						fVolume, pxData->m_ucLooping != 0, pxData->m_fFadeTime);
				}
			}
			break;
		}
		
#ifdef ASURA_USE_METAMUSICZONES
		case ASURA_MSG_METAMUSIC_ACTIVATEZONE :
		case ASURA_MSG_METAMUSIC_DEACTIVATEZONE :
#endif
		case ASURA_MSG_METAMUSIC_PLAY :
		case ASURA_MSG_METAMUSIC_CHANGESTATE :
		case ASURA_MSG_METAMUSIC_RESTARTLASTTRACK :
			//these are handled by the meta music system
			Asura_MetaMusic_System::HandleMessage(pxMessage);
			break;
#endif	//!defined(ASURA_SUPPORT_DYNAMIC_MUSIC_SYSTEM)

		case ASURA_MSG_ENVTEXTUREANIMATION :
			Asura_TextureAnimation_System::HandleMessage(pxMessage);
			break;

		case ASURA_MSG_EXPLOSION_CREATE:
		{
			Asura_Assert( false, "Explosion system deprecated" );
			break;
		}
        
#ifdef ASURA_SUPPORT_COMMAND_CONSOLE
#ifdef ASURA_SUPPORT_COMMAND_CONSOLE_REMOTE
        case ASURA_MSG_COMMANDCONSOLE_REMOTE_NONCE:
        case ASURA_MSG_COMMANDCONSOLE_REMOTE_EXEC_CMD_RESULT:
            Asura_CommandConsole_Remote::ProcessMessage( pxMessage );
            break;
#endif //#ifdef ASURA_SUPPORT_COMMAND_CONSOLE_REMOTE
#endif //#ifdef ASURA_SUPPORT_COMMAND_CONSOLE

        case ASURA_MSG_PLAYERDISCONNECTED:
		{
            // This is sent to the client when the server wants to force them
            // to disconnect, say because it's shutting down or because they
            // have been forcibly removed by an administrator.
			const Asura_MsgData_PlayerDisconnected* pxData = reinterpret_cast
				<const Asura_MsgData_PlayerDisconnected*>(pxMessage->GetData());
			if(pxData)
			{
				Asura_Network::SetReasonForDisconnection(pxData->m_eReason);
			}

            SetConnectionOkay( false );
            break;
		}

// OR - 23/11/2004 16:17:59 - for BHD. Need to have the project handle these at the moment. 
// some files will be moved to asura once it's been finished, and all will be well.
#if 0 //#ifdef ASURA_SUPPORT_GAMESPY_VOICE
		case ASURA_MSG_VOICEDATA:
		{
			// pass the voice data to the gamespy voice api
			const u_char* pucData = reinterpret_cast<const u_char*>(pxMessage->GetData());
			Asura_GameSpy_Voice::PlayVoicePacket( pucData, pxMessage->GetDataSize() );
			break;
		}
#endif // #ifdef ASURA_SUPPORT_GAMESPY_VOICE

		// JGP - handle FSFX message

#ifdef ASURA_USE_FSFX
	 	case ASURA_MSG_SET_FSFX:
 		{
 			const Asura_Hash_ID	uTemplateHash	= *( static_cast<const Asura_Hash_ID*>( pxMessage->GetData() ) );

			if(uTemplateHash != ASURA_HASH_ID_UNSET)
			{
				Asura_FSFX_System::SetValueForAllHandlers(uTemplateHash, 1.0f);
			}
 			break;
 		}

	 	case ASURA_MSG_SET_FSFX_NEW:
 		{
			const Asura_FSFX_Message* const pxFSFXMessage = static_cast<const Asura_FSFX_Message*>( pxMessage->GetData() );

			if ( pxFSFXMessage->m_xID != ASURA_HASH_ID_UNSET )
			{		
				Asura_FSFX_System::SetValueForAllHandlers(pxFSFXMessage->m_xID, pxFSFXMessage->m_fValue, pxFSFXMessage->m_fTime);
			}
 			break;
 		}
#endif 

		case ASURA_MSG_SOUND_MIXER_PRESET:
		{
			const Asura_Message_SoundMixerPreset* pxMsg = reinterpret_cast
				<const Asura_Message_SoundMixerPreset*>(pxMessage->GetData());
			Asura_Assert(pxMsg, "no mixer preset data");
			Asura_Sound_Mixer_System::SetPreset( pxMsg->m_uHashID, Asura_Maths::Max( 0.0f, pxMsg->m_fFadeTime) );
			break;
		}
		case ASURA_MSG_SOUND_MIXER_PRESET_QUEUE:
		{
			const Asura_Message_SoundMixerPreset* pxMsg = reinterpret_cast
				<const Asura_Message_SoundMixerPreset*>(pxMessage->GetData());
			Asura_Assert(pxMsg, "no mixer preset data");
			Asura_Sound_Mixer_System::QueuePreset( pxMsg->m_uHashID, pxMsg->m_fFadeTime );
			break;
		}
		case ASURA_MSG_SOUND_MIXER_PRESET_UNQUEUE:
		{
			const Asura_Message_SoundMixerPreset* pxMsg = reinterpret_cast
				<const Asura_Message_SoundMixerPreset*>(pxMessage->GetData());
			Asura_Assert(pxMsg, "no mixer preset data");
			Asura_Sound_Mixer_System::UnqueuePreset( pxMsg->m_uHashID, pxMsg->m_fFadeTime );
			break;
		}

		case ASURA_MSG_SKIP_CUTSCENES:
		{
			// Skip cutscenes on this machine, with no check (message should only be sent if the sender has already checked and validated cutscene skipping)
			Asura_Cutscene_System::RequestSkipCutscenes();
			break;
		}

#ifndef ASURA_USE_AUDIO_SYSTEM
		case ASURA_MSG_SOUND_SET_REVERB:
		{
			const Asura_Message_SoundReverb* pxReverb = reinterpret_cast<const Asura_Message_SoundReverb*>( pxMessage->GetData() );
			Asura_Sound_System::SetReverb( static_cast<const Asura_Sound_System::ReverbType>( pxReverb->m_iReverbID ), 1.0f );
			break;
		}
#endif

#ifdef ASURA_USE_DIALOGUE_SYSTEM
		case ASURA_MSG_DIALOGUE_TRIGGER :
		case ASURA_MSG_DIALOGUE_PLAYLINE :
		case ASURA_MSG_DIALOGUE_PLAYLINEONENTITY :
		case ASURA_MSG_DIALOGUE_CANCELSUBTITLE :
		case ASURA_MSG_DIALOGUE_PLAYLINE_CONTROLLER:
		case ASURA_MSG_DIALOGUE_STOPLINE_CONTROLLER:
		{
			Asura_Dialogue_System::HandleMessage(pxMessage);		
			break;
		}
#endif
/*
// SK - 05/01/2007 - i've left this here (albeit commented out) as an example of how the ASURA_MSG_GUIMENU_ACTIVATE message
//					 will work.  This isn't the correct place to do this at the moment and was just placeholder test code.
	
#ifdef ASURA_USE_GUI_MENU_SYSTEM
		case ASURA_MSG_GUIMENU_ACTIVATE:
		{
			const Asura_Message_GUIMenu_Activate* pxData = static_cast<const Asura_Message_GUIMenu_Activate*>(pxMessage->GetData());
						
			if( Asura_GUIMenu_System::DoesMenuPageExist( pxData->hashMenuPageID) == true)
			{
				Asura_GUIMenu_System::SetMenuPageActiveByID( pxData->hashMenuPageID, true);
				Asura_GUIMenu_MessagePump::PostMessage( pxData->hashMenuPageID, 0, UI_MSG_ON_INIT, 0);
				Asura_GUIMenu_System::SetFocusedMenuByID( pxData->hashMenuPageID);
			}
			break;
		}
#endif
*/

#if !defined(ASURA_DONT_USE_TELEPORTERS)
		case ASURA_MSGID_BEGIN_PLAYER_TELEPORT:
		{
			Asura_Teleport_System::HandleClientMessages(pxMessage);
			break;
		}
#endif	// !defined(ASURA_DONT_USE_TELEPORTERS)

#ifdef ASURA_USE_ATTRACTORS
		case ASURA_MSG_ATTRACTOR_FLAGS :
		{
			Asura_Attractor_System::GetInstance()->HandleMessage(pxMessage);
			break;
		}

#endif

		case ASURA_MSG_STREAMINGBACKGROUNDSOUND_FLAGS :
		{
			Asura_StreamingBackgroundSound_System::HandleMessage(pxMessage);
			break;
		}

#ifdef ASURA_SUPPORT_DYNAMIC_MUSIC_SYSTEM
		case ASURA_MSG_DYNAMIC_MUSIC_TRIGGER:
		{
			Asura_Dynamic_Music_System::HandleMessage( pxMessage );
			break;
		}
#endif

#ifdef ASURA_USE_COLLISIONFX
		case ASURA_MSG_COLLISIONFX_CLIENTUPDATE:
		{
			Asura_CollisionFX_System::HandleClientUpdateMessage(pxMessage);
			break;
		}

		case ASURA_MSG_COLLISIONFX_CLIENTCREATEDECAL:
		{
			Asura_CollisionFX_System::HandleClientCreateDecalMessage(pxMessage);
			break;
		}
#endif //ASURA_USE_COLLISIONFX

		default:
		{
			//Check for platform specific messages. RAR 10/09/2003
			if(Platform_ClientMessageHandler(pxMessage))
			{
				break;
			}
			
			/// Kevin Lea - 13/08/2002 10:11:08 - pass down to game code
			if (s_pfnProject_ClientMessageHandler)
			{
				s_pfnProject_ClientMessageHandler(pxMessage);
			}
			else
			{
				Asura_Assert(0, "Unhandled message");
			}
			break;
		}
	}

}
