//
// Asura_ClientEntity_AdvancedVolumeTrigger.cpp
//
// Created by Richard Rice - 22/11/2004
// 
// Copyright (C) 2004 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"
#include "Entity/Triggers/Asura_ClientEntity_AdvancedVolumeTrigger.h"

#include "ChunkSystem/Asura_Chunk_Stream.h"
#include "Entity/Asura_Entity_Classification.h"


Asura_ClientEntity_AdvancedVolumeTrigger::Asura_ClientEntity_AdvancedVolumeTrigger( Asura_Guid uGuid )
: Asura_ClientEntity_Trigger(uGuid)
{
	m_uFlags = 0;
	m_iListFlags           = 0;
    m_uSpecificGuid        = ASURA_GUID_UNREGISTERED;

	m_iNumberOfVolumes = 1;
	m_pxVolumes = new Asura_OrientedVolume[1];
	m_pxVolumes[0].m_xBox.Zero();
	m_pxVolumes[0].m_xOrient = Asura_Maths::IdentityQuat;
}

Asura_ClientEntity_AdvancedVolumeTrigger::Asura_ClientEntity_AdvancedVolumeTrigger(Asura_Guid uGuid,const char*& pcChunkBuffer)
:Asura_ClientEntity_Trigger(uGuid,pcChunkBuffer)
{
	m_iNumberOfVolumes = 0;
	m_pxVolumes = 0;

	//check the version
	int iVersion;
	ASURA_CHUNK_EXTRACT( pcChunkBuffer, iVersion, int );
    Asura_Assert( iVersion>=3 && iVersion <= Asura_ServerEntity_AdvancedVolumeTrigger::ChunkData::CURRENT_VERSION,
        "Asura_ClientEntity_AdvancedVolumeTrigger - incompatible chunk version number" );

	
	//read in the rest
	Asura_ServerEntity_AdvancedVolumeTrigger::ChunkData xChunkData;
	ASURA_CHUNK_EXTRACT( pcChunkBuffer, xChunkData, Asura_ServerEntity_AdvancedVolumeTrigger::ChunkData );

	// Copy the data into this instance.
	m_iListFlags    = xChunkData.m_iListFlags;
	m_uFlags        = xChunkData.m_uFlags;
	m_uSpecificGuid = xChunkData.m_uSpecificGuid;
	m_iNumberOfVolumes = xChunkData.m_iNumberOfVolumes;


	//allocate volume array , and extract those
	m_pxVolumes = new Asura_OrientedVolume[m_iNumberOfVolumes];
	for(int i=0;i<m_iNumberOfVolumes;i++)
	{
		ASURA_CHUNK_EXTRACT( pcChunkBuffer, m_pxVolumes[i].m_xBox, Asura_Bounding_Box );
		ASURA_CHUNK_EXTRACT( pcChunkBuffer, m_pxVolumes[i].m_xOrient, Asura_Quat );
	}


	if(iVersion <= 3)
	{
		//unused flags will be junk in previous versions
		#ifdef ASURA_TOOLS
		//for tools try to clear all the affected flags
		m_uFlags &= 0x00000003;
		#else
		//outside of tools , just reset the new flag
		//(saves worrying about the endianess of the platform)
		m_bTriggerOnNotOccupied = false;
		#endif
	}
}

Asura_ClientEntity_AdvancedVolumeTrigger::~Asura_ClientEntity_AdvancedVolumeTrigger()
{
	delete [] m_pxVolumes;
}

void Asura_ClientEntity_AdvancedVolumeTrigger::ReadFromChunkStream(Asura_Chunk_Stream& xStream)
{
	// Have to read in parent chunk first rather than version number for compatibility with old 
	// chunkbuffer constructor functionality.
	PARENT::ReadFromChunkStream( xStream );

	int iVersion;
	Asura_ReadFromStream_Bitfield_Wrapper<u_int>	xBitfield(m_uFlags);

	//check the version
	xStream >> iVersion;
    Asura_Assert( iVersion>=3 && iVersion <= Asura_ServerEntity_AdvancedVolumeTrigger::ChunkData::CURRENT_VERSION,
        "Asura_ClientEntity_AdvancedVolumeTrigger - incompatible chunk version number" );

	
	//read in the rest
	xStream >> m_iListFlags;
	xStream >> xBitfield;
	xStream >> m_uSpecificGuid;
	xStream >> m_iNumberOfVolumes;

	// Might already be created, better bin previous volume data...
	if (m_pxVolumes)
	{
		delete [] m_pxVolumes;
	}

	//allocate volume array , and extract those
	m_pxVolumes = new Asura_OrientedVolume[m_iNumberOfVolumes];
	for(int i=0;i<m_iNumberOfVolumes;i++)
	{
		xStream >> m_pxVolumes [i].m_xBox;
		xStream >> m_pxVolumes [i].m_xOrient;
	}

	if(iVersion <= 3)
	{
		//unused flags will be junk in previous versions
		#ifdef ASURA_TOOLS
		//for tools try to clear all the affected flags
		m_uFlags &= 0x00000003;
		#else
		//outside of tools , just reset the new flag
		//(saves worrying about the endianess of the platform)
		m_bTriggerOnNotOccupied = false;
		#endif
	}
}


bool Asura_ClientEntity_AdvancedVolumeTrigger::IsTriggered(void)
{
	if (m_bHasAlreadyTriggered) 
	{
		return false;
	}
	if (IsVolumeOccupied() != (m_bTriggerOnNotOccupied ? true : false))
	{
		m_bHasAlreadyTriggered = true;
		return true;
	}
	return false;
}

bool Asura_ClientEntity_AdvancedVolumeTrigger::IsUnTriggered(void)
{
	if (!m_bHasAlreadyTriggered)
	{
		return false;
	}
	if (IsVolumeOccupied() == (m_bTriggerOnNotOccupied ? true : false))
	{
		m_bHasAlreadyTriggered = false;
		return true;
	}
	return false;
}


bool Asura_ClientEntity_AdvancedVolumeTrigger::Contains(const Asura_Vector_3& xPosition)
{
	for(int i=0;i<m_iNumberOfVolumes;i++)
	{
		if(m_pxVolumes[i].Contains(xPosition))
		{
			return true;
		}
	}
	return false;
}

void Asura_ClientEntity_AdvancedVolumeTrigger::OnUnTrigger()
{
	Asura_ClientEntity_Trigger::OnUnTrigger();
	if(m_bTriggerOnce && m_bActive)
	{
		//deactivate this trigger so it doesn't get triggered again
		OnDeactivation();
		m_bActive = false;
	}
}
