//
// Asura_ServerEntity_MusicTrigger.cpp
//
// Created by Richard Rice - 18/03/2003
// 
// Copyright (C) 2003 Rebellion, All Rights Reserved.
//


#include "Core/Asura.h"

#if !defined(ASURA_SUPPORT_DYNAMIC_MUSIC_SYSTEM)

#include "Entity/Triggers/Asura_ServerEntity_MusicTrigger.h"

// Engine independent.
#include "ChunkSystem/Asura_Chunk_Macros.h"
#include "ChunkSystem/Asura_Chunk_Stream.h"
#include "Debugging/Asura_Assert.h"
#include "Entity/Asura_Entity_Classification.h"
#include "Network/Asura_Network.h"
#include "Network/Asura_Message.h"
#include "Sound/Asura_Music.h"


// (MH - 04.04.2003) version 1: added m_uFlags
// (RAR - 08/26/2004) version 2 : added m_fVolume
#define ASURA_SERVERENTITY_MUSICTRIGGER_VERSION_NUMBER 2

Asura_ServerEntity_MusicTrigger::Asura_ServerEntity_MusicTrigger() 
: Asura_ServerEntity_Activatable(true)
{
	Classification = AsuraEntityClass_MusicTrigger;
	m_iMusicTrack = 0;
	m_fFadeTime = 0.5f;
	m_uFlags = ASURA_MUSICTRIGGER_FLAG_LOOPING;
	m_fVolume = 1.0f;
}

Asura_ServerEntity_MusicTrigger::Asura_ServerEntity_MusicTrigger(Asura_Guid uGuid) 
: Asura_ServerEntity_Activatable(uGuid)	
{
	Classification = AsuraEntityClass_MusicTrigger;
	m_iMusicTrack = 0;
	m_fFadeTime = 0.5f;
	m_uFlags = ASURA_MUSICTRIGGER_FLAG_LOOPING;
	m_fVolume = 1.0f;
}

Asura_ServerEntity_MusicTrigger::Asura_ServerEntity_MusicTrigger(Asura_Guid uGuid,const char*& pcChunkBuffer)
:Asura_ServerEntity_Activatable(uGuid,pcChunkBuffer)
{
	Classification = AsuraEntityClass_MusicTrigger;
	
	//check the version
	int iVersion;
	ASURA_CHUNK_EXTRACT( pcChunkBuffer, iVersion,int);
	Asura_Assert(iVersion <= ASURA_SERVERENTITY_MUSICTRIGGER_VERSION_NUMBER, "FATAL ERROR: unknown version number for Asura_ServerEntity_MusicTrigger");

	//read in the rest
	ASURA_CHUNK_EXTRACT( pcChunkBuffer, m_iMusicTrack, int );
	ASURA_CHUNK_EXTRACT( pcChunkBuffer, m_fFadeTime, float );
	if (iVersion >= 1)
	{
		ASURA_CHUNK_EXTRACT( pcChunkBuffer, m_uFlags, u_int );
	}
	else
	{
		m_uFlags = ASURA_MUSICTRIGGER_FLAG_LOOPING;
	}
	if(iVersion >= 2)
	{
		ASURA_CHUNK_EXTRACT( pcChunkBuffer, m_fVolume, float );
	}
	else
	{
		m_fVolume = 1.0f;
	}
}

void Asura_ServerEntity_MusicTrigger::CreateFromChunkBuffer(Asura_Guid uGuid, const char*& pcChunkBuffer)
{
#ifdef TEST_ENTITY_CHUNK_STREAM
	TestStream<Asura_ServerEntity_MusicTrigger>(uGuid, pcChunkBuffer);
#endif
	new Asura_ServerEntity_MusicTrigger(uGuid, pcChunkBuffer);
}

void Asura_ServerEntity_MusicTrigger::OnTrigger()
{
	Asura_ServerEntity_Activatable::OnTrigger();


	//send a message to the client machines to play the music track
    Asura_Message* pxMessage = Asura_Network::CreateMessage(ASURA_MSG_MUSICSYSTEM_PLAY,sizeof(Asura_MsgData_MusicSystem_Play));
    Asura_MsgData_MusicSystem_Play* pxData = (Asura_MsgData_MusicSystem_Play*) pxMessage->GetData();

	Asura_Assert(m_iMusicTrack>=0 && m_iMusicTrack<=255,"Track index too large to fit in message");
	pxData->m_fFadeTime = m_fFadeTime;
	pxData->m_ucMusicTrack = (unsigned char)m_iMusicTrack;
	pxData->m_ucLooping = static_cast<u_char>(m_uFlags & ASURA_MUSICTRIGGER_FLAG_LOOPING);

	int iVolume = Asura_Maths::FloatToInt(m_fVolume*128.0f);
	iVolume = Asura_Maths::ClampToRange(iVolume,0,255);
	pxData->m_ucVolume = (u_char) iVolume;

    pxMessage->To = ASURA_GUID_ALL_CLIENTMACHINES;
    pxMessage->From = Guid;

    Asura_Network::Send(pxMessage);
}



int Asura_ServerEntity_MusicTrigger::GetChunkBufferSize()
{
	return Asura_ServerEntity_Activatable::GetChunkBufferSize()
           +sizeof(int)                 // version
           +sizeof(int)                // music track
           +sizeof(float)              // fade time
		   +sizeof(u_int)				// flags
		   +sizeof(float);				// volume
}

void Asura_ServerEntity_MusicTrigger::FillInChunkBuffer(char*& pcChunkBuffer)
{
	/*
	This entity type can be used in template files , so any changes to FillInChunkBuffer may
	require ApplyChangesForTemplateInstance() to be updated as well.
	Please see the comment at the top of Tools/EntityTemplate/Tools_EntityTemplate_System.h before 
	making any changes.
	RAR 29/04/2004
	*/
	Asura_ServerEntity_Activatable::FillInChunkBuffer(pcChunkBuffer);

	int iVersion = ASURA_SERVERENTITY_MUSICTRIGGER_VERSION_NUMBER;
	ASURA_CHUNK_FILLANDVERIFY( pcChunkBuffer, iVersion,int);

	ASURA_CHUNK_FILLANDVERIFY( pcChunkBuffer, m_iMusicTrack, int );
	ASURA_CHUNK_FILLANDVERIFY( pcChunkBuffer, m_fFadeTime, float );
	// Uses bitmask rather than bitfield, so don't bit flip
	ASURA_CHUNK_FILLANDVERIFY( pcChunkBuffer, m_uFlags, u_int);
	ASURA_CHUNK_FILLANDVERIFY( pcChunkBuffer, m_fVolume, float );
}

void Asura_ServerEntity_MusicTrigger::WriteToChunkStream(Asura_Chunk_Stream& xStream) const
{
	// Wrong order - should really be version number first

	// Parent...
	Asura_ServerEntity_Activatable::WriteToChunkStream(xStream);

	// Version...
	int iVersion = ASURA_SERVERENTITY_MUSICTRIGGER_VERSION_NUMBER;
	xStream << iVersion;

	// Child....
	xStream << m_iMusicTrack;
	xStream << m_fFadeTime;
	xStream << m_uFlags;
	xStream << m_fVolume;
}

void Asura_ServerEntity_MusicTrigger::ReadFromChunkStream(Asura_Chunk_Stream& xStream)
{
	// Wrong order - should be version number first

	// Parent...
	Asura_ServerEntity_Activatable::ReadFromChunkStream(xStream);

	// Version...
	int iVersion = 0;
	xStream >> iVersion;
	Asura_Assert(iVersion <= ASURA_SERVERENTITY_MUSICTRIGGER_VERSION_NUMBER, "FATAL ERROR: unknown version number for Asura_ServerEntity_MusicTrigger");

	// Child....
	xStream >> m_iMusicTrack;
	xStream >> m_fFadeTime;

	// Version handling
	if (iVersion >= 1)
	{
		xStream >> m_uFlags;
	}
	else
	{
		m_uFlags = ASURA_MUSICTRIGGER_FLAG_LOOPING;
	}
	if(iVersion >= 2)
	{
		xStream >> m_fVolume;
	}
	else
	{
		m_fVolume = 1.0f;
	}	
}

#endif	//!defined(ASURA_SUPPORT_DYNAMIC_MUSIC_SYSTEM)
