//////////////////////////////////////////////////////////////////////////////
//
// AVP_ServerEntity_InteractToolReceptacle.h
//
// Created by AJK 24/11/2008
//
// Copyright (c) 2008 Rebellion. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////////

#include "Core/Asura.h"

// This file's header.
#include "Entity/PhysicalObject/Interact/ToolReceptacle/AVP_ServerEntity_InteractToolReceptacle.h"

// Asura
#include "Entity/Asura_StaticMessage_System.h"

//AVP
#include "Entity/PhysicalObject/Interact/ToolReceptacle/AVP_Messages_InteractToolReceptacle.h"
#include "Entity/AVP_Entity_Classification.h"
#include "Entity/AVP_Messages.h"
#include "Entity/PhysicalObject/Actor/AVP_Actor_Messages.h"
#include "Entity/PhysicalObject/Actor/AVP_ServerEntity_Actor.h"
#include "Entity/PhysicalObject/Interact/ToolReceptacle/AVP_ClientEntity_InteractToolReceptacle.h"
#include "Entity/PhysicalObject/Pickup/AVP_ServerEntity_Pickup.h"

#ifdef ASURA_TOOLS
#include "EntityTemplate/Tools_EntityTemplate_System.h"
#endif

Asura_Hashed_List<AVP_ServerEntity_InteractToolReceptacle> AVP_ServerEntity_InteractToolReceptacle::s_xList;

AVP_ServerEntity_InteractToolReceptacle::AVP_ServerEntity_InteractToolReceptacle( Asura_Guid uGuid ) 
: Asura_Entity_Server( uGuid )
, PARENT( uGuid )
, m_uFlags( 0 )
, m_uToolGuid(ASURA_GUID_UNREGISTERED)
, m_uLastToolGuid(ASURA_GUID_UNREGISTERED)
, m_uAttachMarker(ASURA_HASH_ID_UNSET)
{
	Classification = AVP_ENTITYCLASS_INTERACT_TOOL_RECEPTACLE;
	s_xList.AddToList(this);
}

AVP_ServerEntity_InteractToolReceptacle::~AVP_ServerEntity_InteractToolReceptacle()
{
	s_xList.RemoveFromList(this);
}

void AVP_ServerEntity_InteractToolReceptacle::ReadFromChunkStream(Asura_Chunk_Stream& xStream)
{
	int iCurrentChunkVersion;

	xStream >> iCurrentChunkVersion;

	switch ( iCurrentChunkVersion )
	{
	case CURRENT_CHUNK_VERSION :
		{
			PARENT::ReadFromChunkStream(xStream);
			xStream >> m_uFlags;       // Tool is in or not
			xStream >> m_uToolGuid;
			break;
		}
	default :
		{
			Asura_Assertf(false, ("Unknown chunk version (%d) in AVP_ServerEntity_InteractToolReceptacle", iCurrentChunkVersion));
			break;
		}
	}
}

#ifdef ASURA_TOOLS
void AVP_ServerEntity_InteractToolReceptacle::ApplyChangesForTemplateInstance( Tools_EntityTemplateInstance* pxInstance )
{
	PARENT::ApplyChangesForTemplateInstance(pxInstance);

	m_uToolGuid = pxInstance->ConvertGuid(m_uToolGuid);
}
#endif // #ifdef ASURA_TOOLS

void AVP_ServerEntity_InteractToolReceptacle::PostLoadInitialise()
{
	PARENT::PostLoadInitialise();
	if (IsToolInside()) AttachTool(ASURA_HASH_ID_UNSET);

}

void AVP_ServerEntity_InteractToolReceptacle::AttachTool(Asura_Guid uActorGuid) const
{
	// Unhide the Tool
	AVP_ServerEntity_Pickup* pxPickup = AVP_ServerEntity_Pickup::FindEntity(m_uToolGuid);
	if(pxPickup)
	{	
		// Send onDropped message, if it was inserted by the player
		if ( uActorGuid != ASURA_HASH_ID_UNSET)	pxPickup->SendDroppedMessage();

		// Will be hidden if not created as Tool inside pickup, so unhide it
		pxPickup->SetHidden(false);

		// deactivate physical object
		pxPickup->GetPhysicsObject()->SetIgnore(true);

		// Disable pickup
		pxPickup->SetEnabled(false);

		Asura_Message*	pxMessage = NULL;

		if ( pxPickup->GetParentGuid() != ASURA_GUID_UNREGISTERED )
		{
			// Send the message to unlink from the actor
			const AVP_ServerEntity_Actor* pxActor = AVP_ServerEntity_Actor::FindEntity(uActorGuid);
			if(pxActor)
			{
				// Detach it from parent
				pxMessage = Asura_Network::CreateMessage(ASURA_MSG_UNLINK_FROM_PARENT);

				if(pxMessage)
				{

						pxMessage->SetFromGuid( GetGuid() );
						pxMessage->SetToGuid( m_uToolGuid );

						Asura_Network::Send( pxMessage );
				}
			}
		}

		pxMessage = Asura_Network::CreateMessage(ASURA_MSG_LINK_TO_PARENT, sizeof(Asura_Message_PhysicalObject_LinkToParent));

		if(pxMessage)
		{
			Asura_Message_PhysicalObject_LinkToParent*	pxData	= static_cast<Asura_Message_PhysicalObject_LinkToParent*>( pxMessage->GetData() );

			// Create and send the message...
			pxData->SetParentGuid( GetGuid());

			pxData->SetMarkerHash( m_uAttachMarker );

			pxMessage->SetFromGuid( GetGuid() );
			pxMessage->SetToGuid( m_uToolGuid );

			Asura_Network::Send( pxMessage );
		}
	}
	else
	{
		Asura_Assert(false, "Couldn't find Tool server pickup!");
	}
}

void AVP_ServerEntity_InteractToolReceptacle::DettachTool() const
{
	// Unhide the Tool
	AVP_ServerEntity_Pickup* pxPickup = AVP_ServerEntity_Pickup::FindEntity(m_uToolGuid);
	if(pxPickup)
	{	
		Asura_Message*	pxMessage	= Asura_Network::CreateMessage(ASURA_MSG_UNLINK_FROM_PARENT);

		if(pxMessage)
		{
			// Send the message...
			pxMessage->SetFromGuid( GetGuid() );
			pxMessage->SetToGuid( m_uToolGuid );

			Asura_Network::Send( pxMessage );
		}
	}
}

void AVP_ServerEntity_InteractToolReceptacle::WriteToChunkStream(Asura_Chunk_Stream& xStream) const
{
	xStream << CURRENT_CHUNK_VERSION;
	
	PARENT::WriteToChunkStream( xStream );

	xStream << m_uFlags;
	xStream << m_uToolGuid;

}

void AVP_ServerEntity_InteractToolReceptacle::MakeCreateMessage( Asura_Guid uRequestingClient, bool bSendGuaranteed /*= false*/ )
{
	Asura_Message* pxMessage = Asura_Network::CreateMessage(ASURA_MSG_CLIENTCREATE, sizeof( AVP_Message_InteractToolReceptacle_ClientCreate ), GetClassification());
	if(pxMessage)
	{
		AVP_Message_InteractToolReceptacle_ClientCreate* pxData = static_cast< AVP_Message_InteractToolReceptacle_ClientCreate* >( pxMessage->GetData() );
		pxData->FillInteractionObject(this);

		pxMessage->SetToGuid( ASURA_GUID_MY_CLIENT_ENTITIES );
		pxMessage->SetFromGuid( GetGuid() );
		if (bSendGuaranteed)
		{
			pxMessage->UseGuaranteedDelivery();
		}
		Asura_Network::SendToSpecificMachine( pxMessage, uRequestingClient );
	}
}

void AVP_ServerEntity_InteractToolReceptacle::InsertTool(Asura_Guid uToolGuid, Asura_Guid uActorGuid)
{
	OnTurnOn();
	SetToolInside(true);
	SetToolGuid(uToolGuid);
	AttachTool(uActorGuid);

	//Send message to client entities that a Tool is in
	Asura_Message* pxMessage = Asura_Network::CreateMessage(AVP_MSGID_SET_TOOL_IN);
	if( pxMessage )
	{
		pxMessage->SetFromGuid( GetGuid() );
		pxMessage->SetToGuid( ASURA_GUID_MY_CLIENT_ENTITIES );
		Asura_Network::Send(pxMessage);
	}
}

void AVP_ServerEntity_InteractToolReceptacle::RemoveTool()
{
	OnTurnOff();
	SetToolInside(false);
	DettachTool();
	SetToolGuid(ASURA_GUID_UNREGISTERED);

	//Send message to client entities that a Tool is out
	Asura_Message* pxMessage = Asura_Network::CreateMessage(AVP_MSGID_SET_TOOL_OUT);
	if( pxMessage )
	{
		pxMessage->SetFromGuid( GetGuid() );
		pxMessage->SetToGuid( ASURA_GUID_MY_CLIENT_ENTITIES );
		Asura_Network::Send(pxMessage);
	}
}