/*=========================================================================
*
* EDTSpec.cpp :  EDT_SpecificEditor : Implementation file.
*
*
* Version			1.0
* Creation date
* Revision date
*
* Shaitan
*=======================================================================*/

#include "stdafx.h"

#include "itf/customid.h"
#ifdef ACTIVE_EDITOR
#include "acp_base.h"

#include "geo.h"
#include "gli.h"
#include "col.h"
#define HieFriend
#include "spo.h"
#include "lst.hpp"
#undef HieFriend

#include "IncMEC.h"
// Shaitan Clean Env {
//#include "ENV.h"
//End Shaitan Clean Env }
#include "snd.h"
#include "incSCT.h"

#include "ITF.h"

#include "EDTSpec.hpp"
#include "EDTBase.hpp"
#include "EDTSObj.hpp"

#include <direct.h>

#define	C_lNbSpecificEntries		0

#define M_GetSpecificInterface()	(GetEditor()->GetInterface()->GetSpecificInterface())

//CPA2 Stegaru Cristian 98-02
#include "EDTModif.hpp"
//End CPA2 Stegaru Cristian 98-02

//#################################################################################
// CONSTRUCT
//#################################################################################
EDT_SpecificEditor::EDT_SpecificEditor (EDT_HierarchyEditor *pEditor)
{
	m_bIsLoadingWorld = FALSE;
	m_pEditor		  = pEditor;
}

EDT_SpecificEditor::~EDT_SpecificEditor (void)
{

}

//#################################################################################
// INITS
//#################################################################################

void EDT_SpecificEditor::fn_vSpecificInit (void)
{
	// init parameters
	m_bIsLoadingWorld = FALSE;
}


//#################################################################################
// SUBMENU
//#################################################################################

/*===========================================================================
*		Description:	Fill Submenu with specific commands
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
long EDT_SpecificEditor::fn_lDefineSubmenu (EDT_SubMenu *p_oSubMenu, UINT uiStartID)
{
	return C_lNbSpecificEntries;
}

/*===========================================================================
*		Description:	answer to submenu specific commands
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_SpecificEditor::fn_vOnSubmenuCommand	(UINT uiCmdMsg)
{
/*
	switch (uiCmdMsg)
	{
		case C_ui_DisplayWorldAction:
			SetDisplayMode(E_dm_DrawWorld);
			break;
		case C_ui_DisplaySectorAction:
			SetDisplayMode(E_dm_DrawOnlyCurrentSector);
			break;
	}
*/
}


//#################################################################################
// SUPER OBJECT TYPE AND LEVEL
//#################################################################################
/*===========================================================================
*		Description:	check if new type is valid
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_SpecificEditor::fn_bCanChangeTypeSO (EDT_SuperObject *pEdObj, tdeTypeSO eType)
{
	CPA_SuperObject *pParent;
	
	if (!M_GetSpecificInterface()->fn_bHasValidWorld(!m_bIsLoadingWorld))
		return TRUE;

	// check parent
	pParent = pEdObj->GetSuperObjectFather();
	if (!pParent)
		return TRUE;

	// protected objects are free
	if ((eType == C_Protected)&&(pEdObj->GetSuperObjectOwner()))
		return TRUE;
	// else type must be coherent with hierarchy
	return (pParent->GetTypeSO() == eType);
}


//#################################################################################
// DEFAULT PARENT
//#################################################################################

//ANNECY Shaitan EmptySectors 25/02/98
/*===========================================================================
*		Description:	find parent from pos
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                           Author:
*=========================================================================*/
/*
EDT_SuperObject * EDT_SpecificEditor::GetDefaultParentFromPos (tdstPosition *p_stPosition, tdeTypeSO eTypeInsert)
{
	// invalid world => no default parent
	return (EDT_SuperObject *) M_GetSpecificInterface()->GetDefaultParentFromPos(p_stPosition, eTypeInsert);
}
*/
//ENDANNECY Shaitan EmptySectors

/*===========================================================================
*		Description:	get parent for copy / paste.
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author:
*=========================================================================*/
EDT_SuperObject * EDT_SpecificEditor::GetDefaultParentForPaste (EDT_SuperObject *pEdObj)
{
//ANNECY Shaitan EmptySectors 25/02/98
//	CPA_SuperObject *pSector;
//ENDANNECY Shaitan EmptySectors
	
	// invalid world => no default parent
	if (!M_GetSpecificInterface()->fn_bHasValidWorld(!m_bIsLoadingWorld))
		return NULL;
	
	// protected objects have no default parent
	if (pEdObj->GetTypeSO() == C_Protected)
		return NULL;

	// dynamic objects => dynamic root
	if (pEdObj->GetTypeSO() == C_Dynamic)
		return (EDT_SuperObject *) M_GetSpecificInterface()->GetDynamicRoot();

	// static object => current sector
	if (pEdObj->GetTypeSO() == C_Static)
	{
//ANNECY Shaitan EmptySectors 25/02/98
		return (EDT_SuperObject *) M_GetSpecificInterface()->GetSuperObjectCurrentSector(pEdObj);
//		pSector = M_GetSpecificInterface()->GetSuperObjectCurrentSector(pEdObj);
//		if (pSector)
//			return (EDT_SuperObject *) pSector->GetSuperObjectFirstChild();
//ENDANNECY Shaitan EmptySectors
	}

	// others => invalid
	return NULL;
}


//#################################################################################
// PERMISSIONS
//#################################################################################

/*==========================================================================
*		Description:	check if parent is available
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                                                                                          Author:
*=========================================================================*/
BOOL EDT_SpecificEditor::fn_bCanBeParent (EDT_SuperObject *pNewParent, EDT_SuperObject *pChild)
{
	return fn_bCheckParentAndType(pChild, pNewParent);
}

/*==========================================================================
==========================================================================*/
BOOL EDT_SpecificEditor::fn_bCanBeParent (EDT_SuperObject *pNewParent, CPA_List<CPA_SuperObject> *pListOfChilds)
{
	CPA_SuperObject *pElem;
	POSITION		pos;

	// check all element in the list
	for (pElem = pListOfChilds->GetHeadElement(pos); pElem;
		 pElem = pListOfChilds->GetNextElement(pos))
	{
		if (!fn_bCheckParentAndType((EDT_SuperObject *) pElem, pNewParent))
			return FALSE;
	}

	// no objection
	return TRUE;
}


/*==========================================================================
*		Description:	check if move is available
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                                                                                          Author:
*=========================================================================*/
long EDT_SpecificEditor::fn_lCanMoveObjects (CPA_List<CPA_SuperObject> *pObjectsToMove)
{
	CPA_SuperObject *pElem;
	POSITION		pos;
	long			lNbBreak = 0;

	// invalid world => only protected are free
	if (!M_GetSpecificInterface()->fn_bHasValidWorld(!m_bIsLoadingWorld))
	{
		// only protected objects are free
		for (pElem = pObjectsToMove->GetHeadElement(pos); pElem;
			 pElem = pObjectsToMove->GetNextElement(pos))
		{
			if (pElem->GetTypeSO() != C_Protected)
				return -1;
		}
		// no condition
		return 0;
	}
	// reinit list modifs
	while (m_pEditor->GetListOfModifParent()->GetCount())
		delete (m_pEditor->GetListOfModifParent()->RemoveTail());
	// check all moved objects
	for (pElem = pObjectsToMove->GetHeadElement(pos); pElem;
		 pElem = pObjectsToMove->GetNextElement(pos))
	{
		if (!fn_bCheckSectorMove((EDT_SuperObject *) pElem, &lNbBreak, TRUE))
			return -1;
	}
	// number of broken links
	return lNbBreak;
}



//#################################################################################
// SECTORS
//#################################################################################

//ANNECY Shaitan EmptySectors 25/02/98
/*===========================================================================
*		Description:	init protection for sectors
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
/*
void EDT_SpecificEditor::fn_vInitSectorsParameters (EDT_SuperObject *pSRoot)
{
	CPA_SuperObject *pSector, *pChild;

	// check all sectors
	for (pSector = pSRoot->GetSuperObjectFirstChild(); pSector;
		 pSector = pSRoot->GetSuperObjectNextChild(pSector))
	{
		// first levels of sectors => protected childs
		for (pChild = pSector->GetSuperObjectFirstChild(); pChild;
			 pChild = pSector->GetSuperObjectNextChild(pChild))
		{
			pChild->SetEditProtected(TRUE);
			pChild->SetSuperObjectOwner(pSector);
		}
	}

}
*/
//ENDANNECY Shaitan EmptySectors

//#################################################################################
// PERMISSIONS
//#################################################################################

/*==========================================================================
*		Description:	check if move is available (recursive function)
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                                                                                          Author:
*=========================================================================*/
BOOL EDT_SpecificEditor::fn_bCheckSectorMove (EDT_SuperObject *pEdObj, long *p_lNbBreak, BOOL bSelected)
{
	CPA_SuperObject *pSector;
	CPA_SuperObject *pParent;
	CPA_SuperObject *pChild;

	// object must stay in a sector
	pSector = M_GetSpecificInterface()->GetSuperObjectCurrentSector(pEdObj);
	if ((pEdObj->GetTypeSO() != C_Protected)&&(!pSector))
		return FALSE;

	// check for Univers Sector
	if (pSector == M_GetSpecificInterface()->GetStaticRoot()->GetSuperObjectLastChild())
	{
		CString csName = pEdObj->GetObject() ? pEdObj->GetObject()->GetName() : pEdObj->GetName();
		if (MessageBox( NULL,
						"  Object " + csName + " is in Univers sector\n"
						"  Are you sure you want to move it here ?\n",
						"Object In Univers Sector",
						MB_YESNO | MB_ICONEXCLAMATION | MB_TASKMODAL | MB_TOPMOST)
			== IDNO)
			return FALSE;
	}

	// only static objects require special handling
	if (pEdObj->GetTypeSO() == C_Static)
	{
		pParent = pEdObj->GetSuperObjectFather();
		// if sector is invalid, create modif parent
		if (pSector != M_GetSpecificInterface()->GetSuperObjectCurrentSector(pParent))
		{
			m_pEditor->GetListOfModifParent()->AddTail( new EDT_SaveParents
//ANNECY Shaitan EmptySectors 25/02/98
//				(pEdObj, (EDT_SuperObject *) pParent, (EDT_SuperObject *) pSector->GetSuperObjectFirstChild()));
				(pEdObj, (EDT_SuperObject *) pParent, (EDT_SuperObject *) pSector));
//ENDANNECY Shaitan EmptySectors
			if (!bSelected)
				*p_lNbBreak++;
		}
	}
	// next level of hierarchy
	for (pChild = pEdObj->GetSuperObjectFirstChild(); pChild;
		 pChild = pEdObj->GetSuperObjectNextChild(pChild))
	{
		if (!fn_bCheckSectorMove((EDT_SuperObject *) pChild, p_lNbBreak, FALSE))
			return FALSE;
	}

	// no objection
	return TRUE;
}


/*===========================================================================
*		Description:	check type
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_SpecificEditor::fn_bCheckParentAndType (EDT_SuperObject *pEdObj, EDT_SuperObject *pParent)
{
	// invalid world => only protected are free
	if (!M_GetSpecificInterface()->fn_bHasValidWorld(!m_bIsLoadingWorld))
		return ((pParent)&&(pEdObj->GetTypeSO() == C_Protected));
		
	// root or NULL are not available
	if ((!pParent)||(pParent == m_pEditor->GetInterface()->GetCurrentWorld()->GetRoot()))
		return FALSE;

	switch (pEdObj->GetTypeSO())
	{
		// protected objects are free, except for roots and sectors
		case C_Protected:
			if ((pParent == M_GetSpecificInterface()->GetDynamicRoot())||(pParent == M_GetSpecificInterface()->GetStaticRoot()))
				return FALSE;
//ANNECY Shaitan NewBorder 13/02/98
//			if (pParent->GetRealTypeName() == C_szSectorTypeName)
//				return FALSE;
//ENDANNECY Shaitan NewBorder
			return TRUE;

		// dynamic => only dynamic root
		case C_Dynamic:
			return (pParent == M_GetSpecificInterface()->GetDynamicRoot());

		// static => same sector
		case C_Static:
			// parent must be static 
			if (pParent->GetTypeSO() != C_Static)
				return FALSE;
//ANNECY Shaitan EmptySectors 25/02/98
			// root is not a valid parent
			if (pParent == M_GetSpecificInterface()->GetStaticRoot())
				return FALSE;
//			// root or sector itself are not valid parent
//			if ((pParent == M_GetSpecificInterface()->GetStaticRoot())||(pParent->GetRealTypeName() == C_szSectorTypeName))
//ENDANNECY Shaitan EmptySectors
			// child must be in the same sector
			if (M_GetSpecificInterface()->GetSuperObjectCurrentSector(pEdObj) != M_GetSpecificInterface()->GetSuperObjectCurrentSector(pParent))
				return FALSE;
//ANNECY Shaitan EmptySectors 25/02/98
			// check super-object status
			if (!fn_bCheckSaveStatus(pEdObj->GetSaveStatus(), pParent))
				return FALSE;
//			// Designer mode => under sector first child
//			if (M_GetSpecificInterface()->GetUserStatus() == E_us_StatusDesign)
//				return (GetDefaultParentForPaste(pEdObj) == pParent);
//ENDANNECY Shaitan EmptySectors
			// no objection
			return TRUE;
	}
	return FALSE;
}

//ANNECY Shaitan EmptySectors 25/02/98
/*===========================================================================
*		Description:	check status
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_SpecificEditor::fn_bCheckSaveStatus (tdeSaveStatus eStatus, EDT_SuperObject *pParent)
{
	tdeSaveStatus eParentStatus = pParent->GetSaveStatus();

	
	switch (eStatus)
	{
		case E_ss_Responsible:
		case E_ss_Modify:
			return (eParentStatus != E_ss_NoSave);
	}

	return TRUE;
}
//ENDANNECY Shaitan EmptySectors

//#################################################################################
// LOAD
//#################################################################################

/*===========================================================================
*		Description:	Load editor infos corresponding to engine current map
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author:
*=========================================================================*/
EDT_SuperObject * EDT_SpecificEditor::fn_pInitEditorMap (HIE_tdxHandleToSuperObject hRoot)
{
	HIE_tdxHandleToSuperObject	hDRoot, hSRoot, hDInactiveRoot;
	CPA_SuperObject				*pRoot, *pDRoot, *pDInactiveRoot, *pSRoot;
	CString						csSectionName;
	char						szFileName[SCR_CV_ui_Cfg_MaxLenName];
	char						szActionName[SCR_CV_ui_Cfg_MaxLenName];
	char						szName[SCR_CV_ui_Cfg_MaxLenName];
	int							iPos;

	// set load mode
	m_bIsLoadingWorld = TRUE;
	
	// get roots
	hDRoot			= HIE_fn_hGetSuperObjectFirstChild(hRoot);
	hDInactiveRoot	= HIE_fn_hGetSuperObjectNextBrother(hDRoot);
	hSRoot			= HIE_fn_hGetSuperObjectLastChild(hRoot);

	// init static file name
	csSectionName = m_pEditor->GetEngineSectionName(hSRoot);
	SCR_fn_v_RdL0_SplitSectionName((char*)(LPCSTR) csSectionName, szFileName, szActionName, szName);
	m_csStaticFileName = szFileName;
	// init dynamic file name
	iPos = m_csStaticFileName.ReverseFind('.');
	m_csDynamicFileName = m_csStaticFileName.Left(iPos) + ".lvl";

	// create root
	pRoot = m_pEditor->GetNewSuperObject(hRoot, E_ss_NoSave, C_NoType, "SO_Root", "");
	pRoot->SetEditProtected(TRUE);
	// create Dynamic Root
	pDRoot = m_pEditor->GetNewSuperObject(hDRoot, E_ss_NoSave, C_Dynamic, "SO_DynamicRoot", "");
	pDRoot->SetEditProtected(TRUE);
	pRoot->AddANewChild(pDRoot, FALSE);
	// create Inactivate Dynamic Root
	pDInactiveRoot = m_pEditor->GetNewSuperObject(hDInactiveRoot, E_ss_NoSave, C_Dynamic, "SO_InactiveDynamicRoot", "");
	pDInactiveRoot->SetEditProtected(TRUE);
	pRoot->AddANewChild(pDInactiveRoot, FALSE);
	// create Static Root
	pSRoot = m_pEditor->GetNewSuperObject(hSRoot, E_ss_NoSave, C_Static, "SO_StaticRoot", m_csStaticFileName);
	pSRoot->SetEditProtected(TRUE);
	pRoot->AddANewChild(pSRoot, FALSE);

	// build dynamic hierarchy
	g_oBaseFrame.mfnv_UpdateTitle("Loading Editor Dynamic Hierarchy");
//	M_GetMainWnd()->UpdateStatus("Loading Editor Dynamic Hierarchy", C_STATUSPANE_INFOS, C_STATUS_NORMAL);
	m_pEditor->fn_vBuildEditorHierarchy(pDRoot, hDRoot);
	// build static hierarchy
	g_oBaseFrame.mfnv_UpdateTitle("Loading Editor Static Hierarchy");
//	M_GetMainWnd()->UpdateStatus("Loading Editor Static Hierarchy", C_STATUSPANE_INFOS, C_STATUS_NORMAL);
	m_pEditor->fn_vBuildEditorHierarchy(pSRoot, hSRoot);
//ANNECY Shaitan EmptySectors 25/02/98
//	// update for sectors
//	M_GetMainWnd()->UpdateStatus("Initializing Sectors", C_STATUSPANE_INFOS, C_STATUS_NORMAL);
//	fn_vInitSectorsParameters((EDT_SuperObject *) pSRoot);
//ENDANNECY Shaitan EmptySectors

	// load all modifs
	//CPA2 Stegaru Cristian 98-02
	csSectionName = m_pEditor->GetSOReferencePath() + GetModifSectionName();
	if (SCR_fn_c_RdL0_IsSectionExists((char *)(LPCTSTR) csSectionName))
	{
		g_oBaseFrame.mfnv_UpdateTitle("Loading temporary modifications");
		//M_GetMainWnd()->UpdateStatus("Loading temporary modifications", C_STATUSPANE_INFOS, C_STATUS_NORMAL);
		SCR_M_RdL0_SetContextLong(1, 0,  (long) m_pEditor);
		SCR_fnp_st_RdL0_AnalyseSection((char *)(LPCTSTR) csSectionName, SCR_CDF_uw_Anl_Normal);
	}
	//End CPA2 Stegaru Cristian 98-02
	// new editor root
//	g_oBaseFrame.mfnv_UpdateTitle("Editor Hierarchy Load >> 100%");
//	M_GetMainWnd()->UpdateStatus("Editor Hierarchy Load >> 100%", C_STATUSPANE_INFOS, C_STATUS_NORMAL);
	m_bIsLoadingWorld = FALSE;
	return (EDT_SuperObject *) pRoot;
}

/*===========================================================================
*		Description:	Get modifications section name
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author:
*=========================================================================*/
CString EDT_SpecificEditor::GetModifSectionName (void)
{
	CString	csSectionName;
	char	szModifName[SCR_CV_ui_Cfg_MaxLenName];

	//CPA2 Stegaru Cristian 98-02
	CString csFileName;
	int iPos = m_csStaticFileName.ReverseFind ('.');
	ASSERT (-1 != iPos);
	csFileName = m_csStaticFileName.Left (iPos) + szModifExt;
	//End CPA2 Stegaru Cristian 98-02
	SCR_fn_v_RdL0_ComputeSectionName(szModifName, (char*)(LPCSTR)csFileName, "Edit-Modifications", NULL);
	csSectionName = szModifName;

	return csSectionName;
}

/*===========================================================================
*		Description:	init parameters for load
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author:
*=========================================================================*/
void EDT_SpecificEditor::fn_vInitTypeSO (EDT_SuperObject *pEdObj, EDT_SuperObject *pParent)
{
	// init type from hierarchy position
	if (pEdObj->GetTypeSO() == C_NoType)
	{
		if (pEdObj->GetSuperObjectOwner())
			pEdObj->SetTypeSO(C_Protected);
		else
			pEdObj->SetTypeSO(pParent->GetTypeSO());
	}
}



//#################################################################################
// SUPER OBJECT TYPE
//#################################################################################


/*===========================================================================
*		Description:	check if object's type correspond to user status
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_SpecificEditor::fn_bIsValidType (tdeTypeSO eTypeSO)
{
	// invalid world => no condition
	if (!M_GetSpecificInterface()->fn_bHasValidWorld(!m_bIsLoadingWorld))
		return TRUE;
	
	//chbani :desactive le test de USER Statut
	return TRUE;

	switch (eTypeSO)
	{
		// static objects => always temporary modifs
		case C_Static:
			return (M_GetSpecificInterface()->GetUserStatus() != E_us_StatusDesign);
		// dynamic objects => temporary for graphist
		case C_Dynamic:
			return (M_GetSpecificInterface()->GetUserStatus() != E_us_StatusGraphic);
		// protected objets => always free
		case C_Protected:
			return TRUE;
		
		default:
			return FALSE;
	}
}




#endif // ACTIVE_EDITOR