//
// Tools_Entity_CutsceneController_Object.cpp
//
// Created by Richard Rice - 09/05/2002
// 
// Copyright (C) 2002 Rebellion, All Rights Reserved.
//


#include "Core/Asura.h"
#include "Entity/Tools_Entity_CutsceneController_Object.h"

#include "Debugging/Asura_Assert.h"
#include "Entity/Asura_Entity.h"
#include "Entity/Asura_Entity_Classification.h"
#include "Entity/Cutscene/Asura_ServerEntity_CutsceneController.h"
#include "Entity/Asura_StaticMessage_System.h"
#include "Interface/Asura_Dialog.h"
#include "Interface/Asura_Overlay.h"
#include "Mesh/Asura_Mesh_System.h"
#include "Network/Asura_Message.h"

#include "Tools_System.h"
#include "Cutscene/Asura_Cutscene.h"
#include "Cutscene/Asura_Cutscene_System.h"
#include "Cutscene/Asura_Cutscene_Actor.h"
#include "Cutscene/Asura_Cutscene_Event.h"
#include "Entity/Tools_Entity_Data.h"
#include "Load&Save/Tools_SaveAsura.h"
#include "Misc/Tools_Timed_Messages.h"
#include "Misc/Tools_Modal_Overlay.h"
#include "Objects/Tools_Object_System.h"



////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Drop down list for selecting the camera actor for a SetCamera message

class Tools_CutsceneCamera_DropDownList_Dialog : public Asura_Hash_DropDownList_Dialog
{
public :
	Tools_CutsceneCamera_DropDownList_Dialog(Asura_Vector_2& xOffset, Asura_Guid uGuid, Asura_Hash_ID* puSelected)
	:Asura_Hash_DropDownList_Dialog(xOffset)
	{
		//find the cutscene from the controller guid
		m_pxCutscene = 0;
		Tools_Object* pxObject = Tools_Object_System::GetObjectFromGuid(uGuid);
		if(pxObject && pxObject->Type == TOT_Entity_CutsceneController)
		{
			m_pxCutscene = ((Tools_Entity_CutsceneController_Object*)pxObject)->GetCutscene();
		}

		Initialise(xOffset,10,puSelected,NULL,"Camera");
	}
protected :

	virtual u_int GetNumberOfHashValues() const
	{
		if(!m_pxCutscene) return 0;
		return m_pxCutscene->GetNumberOfCameras();

	}

	virtual const char* GetNameByIndex(int iIndex) const
	{
		if(!m_pxCutscene) return 0;
		const Asura_Cutscene_Actor_Camera* pxCamera = m_pxCutscene->GetCameraByIndex(iIndex);
		return pxCamera ? pxCamera->ActorName.GetString() : 0;
	}

	virtual const char* GetZeroHashText() const {return "*Not Set*";}

private :
	Asura_Cutscene* m_pxCutscene;

};

////////////////////////////////////////////////////////////////////////////////////////////////////////////

Tools_Entity_CutsceneController_Object::Tools_Entity_CutsceneController_Object(Asura_Entity* entity)
:Tools_Entity_Object(entity)
{
	Asura_Assert(entity->GetClassification()==AsuraEntityClass_CutsceneController,"");
	Type = TOT_Entity_CutsceneController;

	Asura_String mesh_name = "ToolsShape_Cutscene";
	Mesh = Asura_Mesh_System::GetMesh(mesh_name);

	//update name/position from the cutscene that this is a controller for
	Asura_ServerEntity_CutsceneController* asuraEntity = (Asura_ServerEntity_CutsceneController*) Entity;
	asuraEntity->ToolsData->Name = asuraEntity->CutsceneName;

	Asura_Cutscene* cutscene =  Asura_Cutscene_System::GetCutscene(asuraEntity->CutsceneName.GetString());
	if(cutscene)
	{
		Position = cutscene->Position;
		asuraEntity->ToolsData->Position = Position;	
		asuraEntity->ToolsData->m_uLightSets = cutscene->m_uLightSets;
	}

	BuildMessageBlockList();
}



void Tools_Entity_CutsceneController_Object::UpdateCutsceneControllersFromCutscenes()
{
	List<Asura_String> nameList;

	//check through all the existing cutscene controllers to see if there are any duds
	List<Tools_Object*> objectList;
	Tools_Object_System::ListObjectsOfType(TOT_Entity_CutsceneController,objectList);

	for(LIF<Tools_Object*> olif(&objectList);!olif.done();olif.next())
	{
		Tools_Entity_CutsceneController_Object* toolsEntity = (Tools_Entity_CutsceneController_Object*) olif();	
		Asura_ServerEntity_CutsceneController* asuraEntity = (Asura_ServerEntity_CutsceneController*) toolsEntity->Entity;

		Asura_Cutscene* cutscene =  Asura_Cutscene_System::GetCutscene(asuraEntity->CutsceneName.GetString());

		if(cutscene)
		{
			olif()->Position = cutscene->Position;
			
			//add to the list of cutscenes that have controllers
			nameList.add_entry(asuraEntity->CutsceneName);

			//while we are checking the cutscene controller entities , make sure that the
			//'check starts active flag' is on. This should in theory always be set while in the tools,
			//but there appears to be some loophole that is allowing it to become 0 (exactly what is
			//still to be determined). Anyway , resetting it here , should fix any previously bugged
			//entited. RAR 30/04/03
			asuraEntity->m_uCheckStartActiveFlag = 1;
		}
		else
		{
			//destroy
			Tools_Timed_Message_System::AddMessage( 0xFF0000, "Removing tools entity %d with missing cutscene named %s", olif()->GetGuid(), asuraEntity->CutsceneName.GetString());
			olif()->Destroy();
		}
	}

	//now check each cutscene to see if it has a controller
	int numberOfCutscenes = Asura_Cutscene_System::GetNumberOfCutscenes();
	for(int i=0;i<numberOfCutscenes;i++)
	{
		Asura_Cutscene* cutscene = Asura_Cutscene_System::GetCutsceneByIndex(i);

		if(nameList.contains(cutscene->GetName())) continue;

        if( !cutscene->NeedsController() ) { continue; }

		//create a controller for this cutscene
		Asura_ServerEntity_CutsceneController* asuraEntity = new Asura_ServerEntity_CutsceneController(cutscene->GetName(),Asura_Entity_System::GetCreatedByToolsGuid());
		//and create the tools object
		new Tools_Entity_CutsceneController_Object(asuraEntity);

		Tools_SaveAsura::SetEntityModified(asuraEntity);
	}
}



bool Tools_Entity_CutsceneController_Object::HandlesThisMessage(int messageID)
{
	if(messageID == ASURA_MSG_ACTIVATE ||
	   messageID == ASURA_MSG_DEACTIVATE ||
	   messageID == ASURA_MSG_ACTIVATECUTSCENEWITHTIME ||
	   messageID == ASURA_MSG_CUTSCENE_ENABLEEVENT ||
	   messageID == ASURA_MSG_CUTSCENE_DISABLEEVENT ||
	   messageID == ASURA_MSG_CUTSCENE_SETCAMERA)
	{
		return true;
	}
	return false;

}

Asura_Cutscene* Tools_Entity_CutsceneController_Object::GetCutscene()
{
	Asura_ServerEntity_CutsceneController* pxAsuraEntity = (Asura_ServerEntity_CutsceneController*) Entity;
	Asura_Cutscene* pxCutscene =  Asura_Cutscene_System::GetCutscene(pxAsuraEntity->CutsceneName.GetString());
	return pxCutscene;
}

bool Tools_Entity_CutsceneController_Object::SubEntityHandlesThisMessage(Asura_Guid uGuid,int iMessageID)
{
	Asura_Cutscene* pxCutscene = GetCutscene();
	if(!pxCutscene) return false;

	if(uGuid == ASURA_GUID_UNREGISTERED) return false;

	//find the actor
	Asura_Cutscene_Actor* pxActor = NULL;
	for(int i=0;i<pxCutscene->NumberOfActors;i++)
	{
		if(pxCutscene->Actors[i]->m_uGuid == uGuid)
		{
			pxActor = pxCutscene->Actors[i];
			break;
		}
	}
	if(!pxActor) return false;

    // Normally with this kind of thing you'd just query the tools object to
    // see whether or not the message type can be accepted. However, that's
    // not really possible with cutscene actors since we only create the
    // corresponding objects when the cutscene itself is currently selected.
    // For now just let the actors themselves filter them.
    if( pxActor->HandlesThisMessage(iMessageID) )
    {
        return true;
    }

	return false;
}

Asura_Guid Tools_Entity_CutsceneController_Object::SelectSubEntity()
{
	Asura_Cutscene* pxCutscene = GetCutscene();
	if(!pxCutscene)
	{
		Tools_Timed_Message_System::AddMessage(0xff0000,"Failed to find cutscene for this object");
		return false;
	}

	ListSelection_Overlay xOverlay("Select actor to receive message");

	if(!pxCutscene->NumberOfActors)
	{
		Tools_Timed_Message_System::AddMessage(0xff0000,"Cutscene doesn't have any actors");
		return ASURA_GUID_UNREGISTERED;
	}

	for(int i=0;i<pxCutscene->NumberOfActors;i++)
	{
		Asura_Cutscene_Actor* pxActor =  pxCutscene->Actors[i];
		xOverlay.AddItem(pxActor->ActorName.GetString(),(int)pxActor->m_uGuid);
	}

	if(!xOverlay.DoModal()) return ASURA_GUID_UNREGISTERED;

	return (Asura_Guid)xOverlay.GetSelectionData();

}

bool Tools_Entity_CutsceneController_Object::IsSubEntity(Asura_Guid uGuid)
{
	Asura_Cutscene* pxCutscene = GetCutscene();
	if(!pxCutscene) return false;

	if(uGuid == ASURA_GUID_UNREGISTERED) return false;

	for(int i=0;i<pxCutscene->NumberOfActors;i++)
	{
		if(pxCutscene->Actors[i]->m_uGuid == uGuid) return true;
	}

	return false;
}

const char* Tools_Entity_CutsceneController_Object::GetSubEntityName(Asura_Guid uGuid)
{
	Asura_Cutscene* pxCutscene = GetCutscene();
	if(pxCutscene)
	{
		//find the actor
		if(uGuid != ASURA_GUID_UNREGISTERED)
		{
			for(int i=0;i<pxCutscene->NumberOfActors;i++)
			{
				if(pxCutscene->Actors[i]->m_uGuid == uGuid)
				{
					return pxCutscene->Actors[i]->ActorName.GetString();
				}
			}
		}
	}
	return Tools_Entity_Object::GetSubEntityName(uGuid);
}

void Tools_Entity_CutsceneController_Object::BuildMessageBlockList()
{
	//get a list of message blocks owned by this cutscene
	while(m_xMessageBlockList.size()) m_xMessageBlockList.delete_first_entry();

	Asura_Cutscene* pxCutscene = GetCutscene();
	if(!pxCutscene) return;

	if(pxCutscene->m_usEndCutsceneMessageBlock != ASURA_STATICMESSAGE_EMPTYBLOCK)
	{
		m_xMessageBlockList.add_entry(pxCutscene->m_usEndCutsceneMessageBlock);
	}

	for(int i=0;i<pxCutscene->NumberOfEvents;i++)
	{
		if(pxCutscene->Events[i]->m_iType == ACET_Trigger)
		{
			Asura_Cutscene_Event_Trigger* pxEvent = (Asura_Cutscene_Event_Trigger*)pxCutscene->Events[i];
			if(pxEvent->m_sMessageBlock != ASURA_STATICMESSAGE_EMPTYBLOCK)
			{
				m_xMessageBlockList.add_entry(pxEvent->m_sMessageBlock);
			}
		}
	}
}

void Tools_Entity_CutsceneController_Object::AddOverlayControls_EventID(struct Asura_StaticMessage* pxMessage,class Asura_Overlay* pxOverlay,class Asura_Vector_2& xOffset)
{
	Asura_Assert(pxMessage->m_pData,"");
	Asura_Message_CutsceneEventID* pxData = (Asura_Message_CutsceneEventID*) pxMessage->m_pData;

	Asura_Dialog* pxDialog = 0;

	pxDialog = new Asura_Numerical_Dialog("Event ID",xOffset,&pxData->m_iEventID,1,32,1,"%d");
	pxDialog->SetHelpText("ID of the event to enable/disable.\nAll events with this ID in the cutscene will be affected.");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

}

void Tools_Entity_CutsceneController_Object::AddOverlayControls_SetCamera(struct Asura_StaticMessage* pxMessage,class Asura_Overlay* pxOverlay,class Asura_Vector_2& xOffset)
{
	Asura_Assert(pxMessage->m_pData,"");
	Asura_Message_Cutscene_SetCamera* pxData = (Asura_Message_Cutscene_SetCamera*) pxMessage->m_pData;

	Asura_Dialog* pxDialog = 0;
	pxDialog = new Tools_CutsceneCamera_DropDownList_Dialog(xOffset,pxMessage->m_uSendTo,&pxData->m_uCameraHash);
	pxDialog->SetHelpText("The camera actor to switch to.");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();


}

void Tools_Entity_CutsceneController_Object::PreMessageBlockOwnershipCheck()
{
	//Rebuild the message block list , since this won't get updated correctly by any message editing
	BuildMessageBlockList();
}



