// Implementation for the class of Editor Actors Instances
///////////////////////////////////////////////////////////
#include "StdAfx.h"

#include "EDACInst.hpp"

#include "EDACActr.hpp"
#include "EDACModl.hpp"
#include "EDACStrg.hpp"
#include "EDACDgIA.hpp"

//External Modules
#include "ErO.h"
//End of External Modules

#undef CPA_WANTS_IMPORT
#undef CPA_EXPORT
#define CPA_WANTS_EXPORT
    #include "_Actors.hpp"
#undef CPA_WANTS_EXPORT
#define CPA_WANTS_IMPORT

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//****************************************************************
// PROVISOIRE....
//This constructor should not exist in final version....
EdActors_EditorActorInstance::EdActors_EditorActorInstance(	CAR_EDIT_TDSTACTOR *ptdstActor)
														: EdActors_EditorActor(EDCAR_ACTOR_TYPE_INSTANCE) 
{
	//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	// !!!!!!!!!!!!!!!!!!!!!!!!!!!! BE CAREFUL !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	//!! There is no Model for this Instance at that time								  !!
	//!! The Model must be set elsewhere, or Editor won't work correctly	!!
	//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	m_pclModel = NULL;
	m_pclActorModel = NULL;

	m_fn_vSetMotorActor(ptdstActor);

	//Creates datas
	m_fn_vCreateActorMSDataList();

	//Calls special functions
	m_fn_vCallSpecialFunctions();

	m_pri_tdstWatchField.eType = OAC_WATCH_FIELD_TYPE__NONE;
	m_pri_tdstWatchField.p_vData = (void *)this;
	m_pri_tdstWatchField.pclWatchData = NULL;
}												  
												  
//****************************************************************
EdActors_EditorActorInstance::EdActors_EditorActorInstance(	CPA_Actor *pclBaseModel,
																														CPA_Actor *pclActor,
																														CAR_EDIT_TDSTACTOR *p_tdstMotorActor,
																														CPA_SuperObject *p_oSuperObject
																													)
														: EdActors_EditorActor(EDCAR_ACTOR_TYPE_INSTANCE) 
{
	//Sets the pointer to the motor actor now.
	m_pclActor = pclActor;
	//and back-sets the motor actor's pointer on the editor actor
	m_pclActor->m_fn_vSetEditorActor(this);

	//Sets base model pointer
	m_pclActorModel = pclBaseModel;
	if ( pclBaseModel != NULL )
	{
		ERROR_ASSERT( pclBaseModel->m_fn_bIsAModel() );
		m_pclModel = (EdActors_EditorActorModel *)m_pclActorModel->m_fn_pclGetEditorActor();
	}
	else
		m_pclModel = NULL;

	//Sets Family
	if ( m_pclModel != NULL )
	{
		//Updates Model's list of Instances
		m_pclModel->m_clInstancesList.AddTail(this);

		m_pclActor->m_pub_fn_vSetFamily(m_pclModel->m_pclActor->m_pub_fn_pclGetFamily());
	}
	else
	{
		m_pclActor->m_pub_fn_vSetFamily(NULL);
	}

	if ( m_pclModel != NULL )
	{
		//Creates a new motor actor
		CAR_EDIT_TDSTACTOR *p_tdstNewMotorActor;
		if ( p_tdstMotorActor == NULL )
 			p_tdstNewMotorActor = (CAR_EDIT_TDSTACTOR *)malloc(sizeof(CAR_EDIT_TDSTACTOR));
		else
			p_tdstNewMotorActor	= p_tdstMotorActor;

 		m_fn_vSetMotorActor(p_tdstNewMotorActor);
		if ( p_tdstMotorActor == NULL )
 			m_fn_vSetMSPointersToNULL();

		//Allocates MS if the corresponding MS in the Model is allocated
		if ( p_tdstMotorActor == NULL )
			m_fn_vAllocateMSAsInModel(m_pclModel);
  
		m_pclActor->fn_vUpdateData(p_tdstNewMotorActor);
		m_pclActor->SetEngineStruct(p_tdstNewMotorActor);
	}

	//Creates datas
	m_fn_vCreateActorMSDataList();

	// if the superobject is given, give it the object
	if ( p_oSuperObject != NULL )
		p_oSuperObject->SetObject(m_pclActor);

 //Updates datas with model's ones (including 'model link' state)
	if ( (m_pclModel != NULL) && (p_tdstMotorActor == NULL) )
		m_fn_vUpdateDatas(m_pclModel, TRUE, CTL_UPDATE_REASON__USE_USER_DEFINED_REASON, OAC_E_ur_InstanciatedFromModel);

	//Calls special functions
	if ( (m_pclModel != NULL) && (p_tdstMotorActor == NULL) )		
		m_fn_vCallSpecialFunctions();	
	//else it's done in m_fn_vSetModel(...)

	m_pri_tdstWatchField.eType = OAC_WATCH_FIELD_TYPE__NONE;
	m_pri_tdstWatchField.p_vData = (void *)this;
	m_pri_tdstWatchField.pclWatchData = NULL;
}												  
												  
//****************************************************************
EdActors_EditorActorInstance::~EdActors_EditorActorInstance()
{
	//Removes from Model's list of Instances
	m_pclModel->m_fn_vRemoveFromInstancesList(this);

	m_fn_vDeleteAllMS();

	//PROVISOIRE !?! ( will be deleted by motor ? )
//	free(m_fn_ptdstGetMotorActor());
}


//****************************************************************
// Looks in the list of datas if they have been modified
void EdActors_EditorActorInstance::m_fn_vLookForModifiedDatas()
{
	EdActors_ActorMiniStructure *pclInstanceCurrentMS;
	CTL_Editor_DataList *pclInstanceDataList;	 
	POSITION InstanceMSPos = m_pclActorCurrentMSList->GetHeadPosition();
	while ( InstanceMSPos != NULL )
	{
		pclInstanceCurrentMS = m_pclActorCurrentMSList->GetNext(InstanceMSPos);

		//Looks only for the developped MS
		if ( pclInstanceCurrentMS->m_fn_bIsAllocated() )
		{
			pclInstanceDataList = pclInstanceCurrentMS->m_pclDataList;

			POSITION DataPos = pclInstanceDataList->GetHeadPosition();
			while ( DataPos != NULL )
				pclInstanceDataList->GetNext(DataPos)->m_fn_vLookIfDataHasBeenModified();
		}
	}
}

//****************************************************************
CPA_Actor *EdActors_EditorActorInstance::m_fn_pclGetModel()
{
	return m_pclActorModel;
}

//****************************************************************
BOOL EdActors_EditorActorInstance::m_pub_fn_bCheckAllMSWithModel()
{
	BOOL bCheckIsOK = TRUE;
	
	EdActors_EditorActorModel *pclEdModel = m_pclModel;

	ERROR_ASSERT( pclEdModel != NULL );

	//Checks the number of MS in Model and in Actor
	long lNumberOfAMSGroupsInInstance = m_clListOfAMSLists.GetCount();
	long lNumberOfAMSGroupsInModel = pclEdModel->m_clListOfAMSLists.GetCount();
	
	CString csHeaderMessage = "Checking MS in the (loaded) Actor '" +  m_fn_csGetActorName();
	csHeaderMessage	+= "', according to its Model ('" + pclEdModel->m_fn_csGetActorName() + "')";

	ERROR_PREPARE_M(g_c_csActorModuleNameForErrors,csHeaderMessage,
									"EdActors_EditorActorInstance::m_pub_fn_bCheckAllMSWithModel()",
									E_ERROR_GRAVITY_FATAL,
									"Number of groups of MS are not the same in Instance and Model");
	ERROR_ASSERT( lNumberOfAMSGroupsInInstance == lNumberOfAMSGroupsInModel );

	EdActors_ActorMiniStructureList *pclInstanceAMSList;
	EdActors_ActorMiniStructureList *pclModelAMSList;
	long lNumberOfAMSInInstance;
	long lNumberOfAMSInModel;
	POSITION ActorPos = m_clListOfAMSLists.GetHeadPosition();
	POSITION ModelPos = pclEdModel->m_clListOfAMSLists.GetHeadPosition();
	while ( ActorPos != NULL )
	{
		ERROR_ASSERT( ModelPos != NULL );

		pclInstanceAMSList = m_clListOfAMSLists.GetNext(ActorPos);
		pclModelAMSList = pclEdModel->m_clListOfAMSLists.GetNext(ModelPos);

		lNumberOfAMSInInstance = pclInstanceAMSList->GetCount();
		lNumberOfAMSInModel = pclModelAMSList->GetCount();

		ERROR_PREPARE_M(g_c_csActorModuleNameForErrors,
										csHeaderMessage,
										"EdActors_EditorActorInstance::m_pub_fn_bCheckAllMSWithModel()",
										E_ERROR_GRAVITY_FATAL,
										"Number of MS are not the same in Instance and Model");
		ERROR_ASSERT( lNumberOfAMSInInstance == lNumberOfAMSInModel );
		
		EdActors_ActorMiniStructure *pclInstanceAMS;
		EdActors_ActorMiniStructure *pclModelAMS;
		POSITION InstanceAMSPos = pclInstanceAMSList->GetHeadPosition();
		POSITION ModelAMSPos = pclModelAMSList->GetHeadPosition();
		while ( InstanceAMSPos != NULL )
		{
			ERROR_ASSERT( ModelAMSPos != NULL );
			
			pclInstanceAMS = pclInstanceAMSList->GetNext(InstanceAMSPos);
			pclModelAMS = pclModelAMSList->GetNext(ModelAMSPos);
			
			if ( pclInstanceAMS->m_fn_bIsAllocated() != pclModelAMS->m_fn_bIsAllocated() )
			{
// Shaitan FastC {
				if (pclModelAMS->m_fn_csGetScriptName() == "Brain")
				{
					pclModelAMS->m_fn_bAllocate(FALSE);
					m_pclActor->m_fn_pclGetModel()->fn_vNotifySave();
				}
				else
				{
//End Shaitan FastC }
					EdActors_Dialog_InconsistentAllocations Dial(	m_pclActor->m_fn_pclGetModel(),
																											m_pclActor,
																											pclModelAMS->m_fn_bIsAllocated(),
																											pclModelAMS,
																											pclInstanceAMS,
																											&g_oBaseFrame);
					//The Dialog does all...
					Dial.DoModal();
// Shaitan FastC {
				}
//End Shaitan FastC }
			}
		}
	}

	return bCheckIsOK;
}

//****************************************************************
// Sets the Model for an Instance who does not have any
// i.e. which has been loaded from a file
void EdActors_EditorActorInstance::m_fn_vSetModel(CPA_Actor *pclNewModel)
{
	ERROR_ASSERT( pclNewModel != NULL );

	m_pclActorModel = pclNewModel;
	m_pclModel = (EdActors_EditorActorModel *)m_pclActorModel->m_fn_pclGetEditorActor();

	//Sets the Model as Owner
	m_pclActor->fn_bSetOwner(pclNewModel);

	//Is a GenDoor if Model is one
	m_pclActor->m_fn_vMakeGenDoor(pclNewModel->m_fn_bIsAGenDoor());

	//Allocates MS if the corresponding MS in the Model is allocated
//	m_fn_vAllocateMSAsInModel(m_pclModel);

	//Creates datas
	m_fn_vCreateActorMSDataList();

	//Updates datas with model's ones (including 'model link' state)
//	m_fn_vUpdateDatas(m_pclModel);
	//PROVISOIRE...
	// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //
	// !!!!! Data Consistency will have to be tested !!!!! //
	// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //

	//Calls special fucntions
	m_fn_vCallSpecialFunctions();

	//Updates model's list of instances
	m_pclModel->m_clInstancesList.AddTail(this);
}

//****************************************************************
void EdActors_EditorActorInstance::m_fn_vCallSpecialFunctions()
{
	POSITION pos = m_clListOfAMSLists.GetHeadPosition();
	POSITION AMSpos;
	EdActors_ActorMiniStructureList *pclAMSList;
	while (	pos != NULL )
	{
		pclAMSList = m_clListOfAMSLists.GetNext(pos);

		AMSpos = pclAMSList->GetHeadPosition();
		while ( AMSpos != NULL )
			pclAMSList->GetNext(AMSpos)->m_fn_bCallSpecialFunction();
	}
}

//****************************************************************
void EdActors_EditorActorInstance::m_pub_fn_vSetLink(CTL_Editor_Data *_pclSourceData,
																										 BOOL _bMustLink)
{
	OAC_fn_tdeSetLink(_pclSourceData, eNot(OAC_fn_tdeGetLink(_pclSourceData)));
}


//***************************************************************************
OAC_tdstWatchField *EdActors_EditorActorInstance::m_pub_fn_p_tdstGetWatchField()
{
	return (&m_pri_tdstWatchField);
}
