// Implementation file for the definition of a State characteristic
///////////////////////////////////////////////////////////////////////
#include "StdAfx.h"

#include "_AInterf.hpp"
#include "CPA_DatS.hpp"

#include "EDACActr.hpp"
#include "EDACCust.hpp"

//External Modules
#include "ErO.h"
#include "TFa.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

//**************************************************************************
//Constructor / Destructor
CPA_Editor_StateData::CPA_Editor_StateData(CString csScriptName,
																					 CTL_Editor_DataList *_pclParentList,
																					 CTL_Editor_Data *pclCurrentBaseData /*= NULL*/)
										: CTL_Editor_Data(CTL_DATA_TYPE__USE_USER_DEFINED_TYPE,
																			csScriptName,
																			_pclParentList,
																			pclCurrentBaseData,
																			OAC_DATA_TYPE__STATE)
{
	m_pri_bIsTheInitialState = ( pclCurrentBaseData != NULL );

 	m_pclCurrentValueForStates = NULL;	 
 	m_pclOldValueForStates = NULL;	 
 	m_pclCurrentValueForActions = NULL;	 
 	m_pclOldValueForActions = NULL;	 
	m_pclKeepedValueForUndoForStates = NULL;
	m_pclKeepedValueForUndoForActions = NULL;
	
	m_pclAction = NULL;

	short wIndex = csScriptName.Find('|');
	CString csFirstScritpName;
	CString csSecondScritpName;
	if ( wIndex != -1 )
	{
		csFirstScritpName = csScriptName.Left(csScriptName.GetLength() - wIndex);
		csSecondScritpName = csScriptName.Right(wIndex - 1);
		m_pro_csDataName = csFirstScritpName;
	}

	//Constructs the List of States (according to Family)
	m_pclEnumDescriptorForStates = new CTL_Editor_EnumDescriptor(csFirstScritpName, 4/*long*/);
	m_pclEnumDescriptorForActions = new CTL_Editor_EnumDescriptor(csSecondScritpName, 4/*long*/);
}

//**************************************************************************
CPA_Editor_StateData::~CPA_Editor_StateData()
{
	delete m_pclEnumDescriptorForStates;
	delete m_pclEnumDescriptorForActions;
}

//Member functions

//**************************************************************************************
//Function called to Init the data
void CPA_Editor_StateData::m_fn_vInitData()
{

}

//**************************************************************************
//Function called to read associated motor's data
void CPA_Editor_StateData::m_fn_vGetMotorData()
{
	long lEnumValue;
	ERROR_ASSERT( m_pclEnumDescriptorForStates->m_fn_ucGetEnumSize() == 4 );
	CTL_fn_vGetMemory(m_pub_fn_pvGetMotorData(), &lEnumValue, 4);

	//Gets corresponding State
	tdxHandleToState hState = (tdxHandleToState)lEnumValue;
	CPA_State *pclState = NULL;
	CPA_Action *pclAction = NULL;

	if ( hState != NULL )
	{
		pclState = (CPA_State *)g_pclInterface->GetMainWorld()->fn_p_oFindObjectWithEngine(hState, C_szStateTypeName);
		pclAction = (pclState != NULL) ? pclState->mfn_p_oGetAction() : NULL;

		CPA_Actor *pclActor = OAC_fn_pclGetParentActorOfData(this)->m_pclActor;
		if ( m_pri_bIsTheInitialState )
		{
			pclActor->m_pub_fn_vSetInitialAction(pclAction);
			pclActor->m_pub_fn_vSetInitialState(pclState);
		}
		else
		{
			pclActor->m_pub_fn_vSetCurrentAction(pclAction);
			pclActor->m_pub_fn_vSetCurrentState(pclState);
		}
	}

	//ANNECY VL PRT 09/04/98{
	if ( M_bEditorsActive() )
	//ENDANNECY VL}
		m_fn_vConstructEnumDescriptors();

	//Updates current value (pointer)	for Actions
	m_pclCurrentValueForActions = m_pclEnumDescriptorForActions->m_fn_pclGetElementFromEnumIndex((long)pclAction);

	//Updates current value (pointer)	for States
	m_pclCurrentValueForStates = m_pclEnumDescriptorForStates->m_fn_pclGetElementFromEnumIndex(lEnumValue);
} 

//**************************************************************************
//Function called to update associated motor's data
void CPA_Editor_StateData::m_fn_vUpdateMotorData(CTL_tdeUpdateReason eReason,
																								 long _lUserDefinedReason /*= 0*/)
{
	ERROR_ASSERT( m_pro_pvMotorData != NULL );

	//Data must be coded on a long (to represent a pointer)
	ERROR_ASSERT( m_pclEnumDescriptorForStates->m_fn_ucGetEnumSize() == 4 );

	m_pclAction = (CPA_Action *)m_pclCurrentValueForActions->m_pub_fn_lGetValue(); 
	tdxHandleToState hDefaultState = NULL;
	if ( (m_pclAction != NULL) && (m_pclAction->mfn_p_oGetDefaultState() != NULL) )
		hDefaultState = (tdxHandleToState)m_pclAction->mfn_p_oGetDefaultState()->GetData();

	CTL_fn_vSetMemory(m_pro_pvMotorData, &hDefaultState, 4);
	
	CPA_Actor *pclActor = OAC_fn_pclGetParentActorOfData(this)->m_pclActor;

	if ( (OAC_tdeUpdateReason)_lUserDefinedReason != OAC_E_ur_InstanciatedFromModel )
	{
 		CPA_State *pclState = (CPA_State *)g_pclInterface->GetMainWorld()->fn_p_oFindObjectWithEngine(hDefaultState, C_szStateTypeName);
		//Sets pointers in parent Actor
		if ( m_pri_bIsTheInitialState )
		{
			pclActor->m_pub_fn_vSetInitialAction(m_pclAction);
			pclActor->m_pub_fn_vSetInitialState(pclState, TRUE);
		}
		else
		{
			pclActor->m_pub_fn_vSetCurrentAction(m_pclAction);
			pclActor->m_pub_fn_vSetCurrentState(pclState);
		}
	}
	
	if ( m_pro_td_p_fn_vDataHasChangedCallBack != NULL )
		m_pro_td_p_fn_vDataHasChangedCallBack(this, eReason, _lUserDefinedReason);

	//Special changes
	m_fn_vDataHasBeenChanged(eReason, _lUserDefinedReason);
}

//************************************************************************
//Function called to update data with another one
void CPA_Editor_StateData::m_fn_vUpdateData(CTL_Editor_Data *pclSourceData,
																						CTL_tdeUpdateReason eReason,
																						long _lUserDefinedReason /*= 0*/)
{
	ERROR_ASSERT( pclSourceData->m_pub_fn_tdeGetDataType() == m_pub_fn_tdeGetDataType() );

	//Asserts Families are the Same
	//TO BE DONE....

	m_pclCurrentValueForStates = ((CPA_Editor_StateData *)pclSourceData)->m_pclCurrentValueForStates;
	m_pclCurrentValueForActions = ((CPA_Editor_StateData *)pclSourceData)->m_pclCurrentValueForActions;
	
	m_fn_vUpdateMotorData(eReason, _lUserDefinedReason);
}

//************************************************************************
//Function called to get a string representing the value of the data
CStringList *CPA_Editor_StateData::m_fn_pcslFormatDataValueString()
{
	m_csStringList.RemoveAll();

	ERROR_ASSERT( m_pclCurrentValueForActions != NULL );
	
	if ( m_pclCurrentValueForActions != NULL )
	{
		CString csStringToReturn;
		csStringToReturn.Format("%s", LPCTSTR(m_pclCurrentValueForActions->m_pub_fn_csGetElementName()));
		m_csStringList.AddTail(csStringToReturn);
	}

	return &m_csStringList;
}

//************************************************************************
//Function called to set the value of the data according to a string representing it
void CPA_Editor_StateData::m_fn_vSetValueWithString(CStringList *pcslValueStringList)
{
	ERROR_ASSERT(pcslValueStringList->GetCount() == 1);
	CString csValueString = pcslValueStringList->GetHead();
	
	m_fn_vConstructEnumDescriptors();

	BOOL bFound = FALSE;
	CTL_Editor_EnumElement *pclElement;
	POSITION pos = m_pclEnumDescriptorForActions->GetHeadPosition();
	while ( (pos != NULL) && (!bFound) )
	{
		pclElement = m_pclEnumDescriptorForActions->GetNext(pos);
		bFound = ( pclElement->m_pub_fn_csGetElementName().CompareNoCase(csValueString) == 0 );
	}
	
	if ( bFound )
		m_pclCurrentValueForActions = pclElement;
	else
	{
		//Default Value
		if ( m_pclEnumDescriptorForActions->GetCount() > 0 )
			m_pclCurrentValueForActions = m_pclEnumDescriptorForActions->GetHead();
		else
			m_pclCurrentValueForActions = NULL;
	}

	m_fn_vUpdateMotorData();
}

//************************************************************************
//Function called to look if data has been modified (by motor for example)
void CPA_Editor_StateData::m_fn_vLookIfDataHasBeenModified()
{				  
	m_fn_vGetMotorData();

	m_pro_bDataHasChanged =			( m_pclCurrentValueForStates != m_pclOldValueForStates )
													||	( m_pclCurrentValueForActions != m_pclOldValueForActions );

	if ( m_pro_bDataHasChanged )
	{
		m_pclOldValueForStates = m_pclCurrentValueForStates;
		m_pclOldValueForActions = m_pclCurrentValueForActions;
	}
}

//************************************************************************
//Function called when data has been really modified (i.e. value is different from previous one)
void CPA_Editor_StateData::m_fn_vDataHasBeenReallyModified()
{

}
 
//Undo
//************************************************************************
//Function called to save the current Value (for Undo)
void CPA_Editor_StateData::m_fn_vKeepCurrentValue()
{
	m_pclKeepedValueForUndoForStates = m_pclCurrentValueForStates;
	m_pclKeepedValueForUndoForActions = m_pclCurrentValueForActions;
}
 
//************************************************************************
//Function called to validate Undo for the current change
void CPA_Editor_StateData::m_fn_vRegisterUndoAction()
{
/*	if ( m_pclKeepedValueForUndo->m_lEnumValue != m_pclCurrentValue->m_lEnumValue )
	{
		EdActors_ActorStateDataModif *pclModif = new EdActors_ActorStateDataModif(this, 
																																						m_pclKeepedValueForUndo,
																																						m_pclCurrentValue);
		m_pclParentActor->m_clUndoManager.AskFor(pclModif);
	}
*/
}


//************************************************************************
//************************************************************************
//Specific functions

//************************************************************************
CTL_Editor_EnumDescriptor *CPA_Editor_StateData::m_fn_pclGetEnumDescriptorForActions()
{
	return m_pclEnumDescriptorForActions;
}

//************************************************************************
CTL_Editor_EnumDescriptor *CPA_Editor_StateData::m_fn_pclGetEnumDescriptorForStates()
{
	return m_pclEnumDescriptorForStates;
}

//************************************************************************
void CPA_Editor_StateData::m_fn_vConstructEnumDescriptors()
{
	//Fills the List of States (according to Family)
	CPA_Family *pclFamily = OAC_fn_pclGetParentActorOfData(this)->m_pclActor->m_pub_fn_pclGetFamily();
	ERROR_ASSERT( pclFamily != NULL );
 	
	m_pclEnumDescriptorForStates->m_fn_vEmptyList();

	////////////////////////////////////////
	//For initial State
	if ( m_pri_bIsTheInitialState )
	{
		POSITION pos = pclFamily->m_oListOfActions.GetHeadPosition();
		CPA_Action *pclCurrentAction;
		while ( pos != NULL )
		{
			pclCurrentAction = pclFamily->m_oListOfActions.GetNext(pos);

			if ( ( pclCurrentAction != NULL ) && ( pclCurrentAction->mfn_p_oGetDefaultState() != NULL ))
				m_pclEnumDescriptorForStates->m_fn_pclAddElement(pclCurrentAction->mfn_p_oGetDefaultState()->GetName(), 
																									(long)(pclCurrentAction->mfn_p_oGetDefaultState()->GetData())
																													);
		}
	}
	//For current State
	else
	{
		POSITION pos = pclFamily->m_oListOfStates.GetHeadPosition();
		CPA_State *pclCurrentState;
		while ( pos != NULL )
		{
			pclCurrentState = pclFamily->m_oListOfStates.GetNext(pos);
			
			if ( pclCurrentState != NULL )
				m_pclEnumDescriptorForStates->m_fn_pclAddElement(pclCurrentState->GetName(),
																													(long)(pclCurrentState->GetData())
																													);
		}
	}

	//Always adds a reference to NULL pointer
	m_pclEnumDescriptorForStates->m_fn_pclAddElement("No State !", 0L);

	////////////////////////////////////////
	//For Initial and Current Action
 	m_pclEnumDescriptorForActions->m_fn_vEmptyList();

	POSITION pos = pclFamily->m_oListOfActions.GetHeadPosition();
	CPA_Action *pclCurrentAction;
	while ( pos != NULL )
	{
		pclCurrentAction = pclFamily->m_oListOfActions.GetNext(pos);

		if ( pclCurrentAction != NULL )
			m_pclEnumDescriptorForActions->m_fn_pclAddElement(	pclCurrentAction->GetName(), 
																													(long)(pclCurrentAction)
																												);
	}

	//Always adds a reference to NULL pointer
	m_pclEnumDescriptorForActions->m_fn_pclAddElement("No Action !", 0L);
}

//************************************************************************
//Called when Action Data has been changed, to update State Data
BOOL CPA_Editor_StateData::m_fn_bSetCurrentValueForStateAccordingToAction()
{
	BOOL bReturn = FALSE;

	if ( m_pclCurrentValueForActions != NULL )
	{
		//Gets new Action
		CPA_Action *pclAction = (CPA_Action *)m_pclCurrentValueForActions->m_pub_fn_lGetValue();

		if ( pclAction != NULL )
		{
			//Gets Action default state
			CPA_State *pclActionDefaultState = pclAction->mfn_p_oGetDefaultState();

			//Sets new current value for State
			if ( pclActionDefaultState != NULL )
				m_pclCurrentValueForStates = m_pclEnumDescriptorForStates->m_fn_pclGetElementFromEnumIndex((long)pclActionDefaultState->GetData());
			else
				m_pclCurrentValueForStates = m_pclEnumDescriptorForStates->m_fn_pclGetElementFromEnumIndex(0L);
		}
		else
			m_pclCurrentValueForStates = m_pclEnumDescriptorForStates->m_fn_pclGetElementFromEnumIndex(0L);

		bReturn = TRUE;
	}
	else
		m_pclCurrentValueForStates = m_pclEnumDescriptorForStates->m_fn_pclGetElementFromEnumIndex(0L);

	return bReturn;
}

//************************************************************************
BOOL CPA_Editor_StateData::m_pub_fn_bIsTheInitialState()
{
	return m_pri_bIsTheInitialState;
}
