//#################################################################################
//
// BASE CLASS OF YOUR DLL interface
//
//#################################################################################

#include "stdafx.h"

#include "ACP_Base.h"
#include "ITF.h"
#include "SCR.h"
#include "DPT.h"

#define D_State_Define
#define D_ObjsTbls_Define
#define D_ZdxStuff_StructureDefine
//#include "DNM.h"
#include "incGAM.h"
#undef D_ZdxStuff_StructureDefine
#undef D_ObjsTbls_Define
#undef D_State_Define


#include "TFA.h"
#include "TAN.h"

#include "ANinterf.hpp"
//#include "AnimView.h"
#include "x:\cpa\main\inc\_EditID.h"


// infos
static CString g_csTANName = "Animation";
static CString g_csTANAuthor = "Vincent Lhullier & Chantal Oury";
static CString g_csTANVersion = "V 6.0.1   18/03/98";
static CString g_csTANFrenchHelpFile = "Animview.hlp";
static CString g_csTANEnglishHelpFile = "";

/*
 *=============================================================================
 * the DLL global definition
 *=============================================================================
 */
tdstDLLIdentity	g_stTAnimIdentity;

static CPA_EditorBase *gs_p_oFamilyDLL;
static CPA_EditorBase *gs_p_oActionDLL;

#define C_uiTANPopupPreLoad		10
/*
 *=============================================================================
 *
 * TAnim_Interface implementation
 *
 *=============================================================================
 */

/*
 *-----------------------------------------------------------------------------
 *  Constructor
 *-----------------------------------------------------------------------------
 */
TAnim_Interface::TAnim_Interface(void)
{
	// ************************** private internal
	m_p_stDLLIdentity = &g_stTAnimIdentity;

    // Does your DLL can output in main game view ?
	m_stBaseDLLDefinition.bCanOutputIn3DView = FALSE;

    // Does your DLL can be refresh by engine ?
	m_stBaseDLLDefinition.bCanBeRefreshedByEngine = FALSE;

    SetEditorInfo(g_csTANName, g_csTANAuthor, g_csTANVersion, g_csTANFrenchHelpFile, g_csTANEnglishHelpFile);

	m_bCompleteLoad = FALSE;
}

/*
 *-----------------------------------------------------------------------------
 *  fn_vJustAfterRegistered
 *-----------------------------------------------------------------------------
 */
void TAnim_Interface::fn_vJustAfterRegistered()
{
	CString a_csType[] = { C_szAnimationTypeName };
	fn_vRegisterObjectsType ( a_csType , 1 ) ;

	mfn_vLoadPreferences();
	gs_p_oFamilyDLL	= GetMainWorld()->GetToolDLLWithName( C_szDLLFamilyName );
	gs_p_oActionDLL	= GetMainWorld()->GetToolDLLWithName( C_szDLLActionName );
}

/*
 *===========================================================================
 *	General Purpose
 *===========================================================================
 */

BOOL TAnim_Interface::fn_bDefineSubMenu(EDT_SubMenu *_p_oEDTSubMenu)
{
//ANNECY Shaitan NewInterface 24/03/98 {
    if (_p_oEDTSubMenu->GetSubMenuType() == C_SubMenuLoad)
//ENDANNECY Shaitan NewInterface }
    {
        _p_oEDTSubMenu->AddAnEntry(this, "PreLoad All Animations", C_uiTANPopupPreLoad );

        return TRUE;
    }
    return FALSE;
}

void TAnim_Interface::_OnSubMenuCommand  (EDT_SubMenu *_p_oEDTSubMenu,UINT uiMsgID)
{
	BOOL bLastCompleteLoad;

//ANNECY Shaitan NewInterface 24/03/98 {
    if( _p_oEDTSubMenu->GetSubMenuType() == C_SubMenuLoad )
//ENDANNECY Shaitan NewInterface }
   {
        switch( uiMsgID )
        {
        case C_uiTANPopupPreLoad:
			bLastCompleteLoad = m_bCompleteLoad;
			m_bCompleteLoad = TRUE;
            mfn_vLoadAllAnimations();
			m_bCompleteLoad = bLastCompleteLoad;
            break;
        }
    }
}

/*
 *-----------------------------------------------------------------------------
 *  OnQueryAction
 *-----------------------------------------------------------------------------
 */
long TAnim_Interface::OnQueryAction	(CPA_EditorBase *p_oSender, WPARAM wAction, LPARAM lParam)
{
	BOOL bLastCompleteLoad;
	switch( wAction )
	{
	case C_cLoadAllAnimsAction:	// load animations of a family using m_bCompleteLoad
		mfn_vLoadAnims( (CPA_Family *) lParam );
		break;
	case C_cPreLoadAllAnimation:	// load animations of a family forcing m_bCompleteLoad
		bLastCompleteLoad = m_bCompleteLoad;
		m_bCompleteLoad = TRUE;
		mfn_vLoadAnims( (CPA_Family *) lParam );
		m_bCompleteLoad = bLastCompleteLoad;
		break;
	case C_cLoadAllAnimations:	// load animations of all families
		mfn_vLoadAllAnimations();
		break;
	case C_cSetCompleteLoadModeTAN:
		m_bCompleteLoad = (BOOL) lParam;
		mfn_vSavePreferences();
		break;
	}
	return 0;
}

/*
 *-----------------------------------------------------------------------------
 *  OnQueryInfo
 *-----------------------------------------------------------------------------
 */
long TAnim_Interface::OnQueryInfos (CPA_EditorBase *p_oSender, WPARAM wAction, LPARAM lParam)
{
	switch( wAction )
	{
	case C_cGetCompleteLoadModeTAN:
		return (long)m_bCompleteLoad;
		break;
	}
	return 0;
}

/*
 *-----------------------------------------------------------------------------
 *  description : load animation
 *-----------------------------------------------------------------------------
 */
BOOL TAnim_Interface::fn_bLoadBaseObject(CPA_BaseObject *p_oObject)
{
//ANNECY CT 20/02/98{
    //if( ! p_oObject -> fn_bIsAvailable() )
    //{
//ENDANNECY CT}

        CPA_Animation *p_oAnim = (CPA_Animation*)p_oObject;

        p_oAnim -> mfn_vLoad();
        return TRUE;

//ANNECY CT 20/02/98{
    //}
    //return FALSE;
//ENDANNECY CT}
}

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

void TAnim_Interface::mfn_vLoadAllAnimations()
{
	if( m_bCompleteLoad )
	{
		CPA_BaseObjectList *p_oFamilyList = gs_p_oFamilyDLL -> GetBaseObjectList( C_szFamilyTypeName );
		Position			xPos = p_oFamilyList -> GetHeadPosition();

		while( xPos )
		{
			CPA_Family *p_oFamily = (CPA_Family*)p_oFamilyList -> GetNext( xPos );
			mfn_vLoadAnims( p_oFamily );
		}
	}
	else
		mfn_vCreateAllLoadedAnimations();
}

/*
 *-----------------------------------------------------------------------------
 *  description : load anims for a given family. Parameters is the family
 *-----------------------------------------------------------------------------
 */
void TAnim_Interface::mfn_vLoadAnims( CPA_Family *_p_oFamily )
{
	WIN32_FIND_DATA	    stWFD;					// structure for searching file
	HANDLE			    hFD;					// handle for searching file
	char			    szSearchName[MAX_PATH];	// name of searched file (including relative path to family dir)
	char			    *p_szName;
    char                szAnimName[MAX_PATH];
    char                *p_cPoint;
	CPA_Animation       *p_oAnim;				// pointer for animation creation
    SCR_tdst_Link_Table *p_stLK = fnp_stGetAnimationLinkTable();
    SCR_tdst_Link_Value *p_xLVa;
    BOOL                 bPreviousLoadingWorld;

	// initialize searching loop (search all file in family directory)
	p_szName = szSearchName + sprintf( szSearchName, "%s\\%s\\", fn_szGetAnimDataPath(), _p_oFamily->fn_p_szGetName() );
	strcpy( p_szName, "*.a3D" );
	hFD = FindFirstFile( szSearchName, &stWFD );

	// stop load if no file found or if an error occurs
	if ( hFD != INVALID_HANDLE_VALUE )
	{
		// save Loading World Mode
		bPreviousLoadingWorld = GetInterface() -> fn_bIsLoadingWorld();
		// no prefix added
		GetInterface() -> SetLoadingWorld( TRUE );

		do
		{
			strcpy( p_szName, stWFD.cFileName );
			// remove ".a3d" from name
			strcpy( szAnimName, stWFD.cFileName );
			if ( (p_cPoint = strrchr( szAnimName, '.' )) != NULL)
				*p_cPoint = 0;

			// get editor object
			p_oAnim = (CPA_Animation*)GetBaseObject( CString(szAnimName), C_szAnimationTypeName, _p_oFamily );
			// get engine object
			p_xLVa = SCR_fnp_st_Link_SearchKey( p_stLK, szSearchName );

			if( p_xLVa )
			{
				// engine exists, must have editor
				if( p_oAnim == NULL )
				{
					// editor object doesn't exist, create it
					p_oAnim = new CPA_Animation(this, _p_oFamily , szAnimName) ;
					// add animation to family
					_p_oFamily->mfn_vAddAnimation( p_oAnim );
				}
				// update engine
				if( ((struct tdstAnim3d_ *)p_oAnim -> GetData()) != ((struct tdstAnim3d_ *)SCR_M_ul_Link_GetValue( p_xLVa )) )
				{
					p_oAnim -> SetData( (struct tdstAnim3d_ *) SCR_M_ul_Link_GetValue( p_xLVa ) );
					p_oAnim -> SetAvailable( TRUE );
				}
			}
			else
			{
				// engine doesn't exist
				// create editor object only if complete load mode and doesn't already exist
				if( m_bCompleteLoad && ( p_oAnim == NULL ) )
				{
					// create editor animation

					p_oAnim = new CPA_Animation(this, _p_oFamily , szAnimName) ;
					// add animation in family
					_p_oFamily->mfn_vAddAnimation( p_oAnim );
					p_oAnim -> SetData( NULL );
					p_oAnim -> SetAvailable( FALSE );
				}
			}
		} while (FindNextFile( hFD, &stWFD) );

		// restore Loading World Mode
		GetInterface() -> SetLoadingWorld( bPreviousLoadingWorld );
		// close FindData handle
		FindClose(hFD);
	}

// Shaitan Correction Anims Specifiques
	char szVersion[255];
	char szPath[255];
	char szRealName[255];
	FILE *hIni;

	// get info from ini file
	hIni = fopen("version.ini", "rt");
	if(hIni == NULL)
		hIni = fopen("x:\\cpa\\exe\\main\\version.ini", "rt");
	if(hIni)
	{
		fgets(szVersion, 49, hIni);
		while(!isalnum(szVersion[strlen(szVersion) - 1]))
			szVersion[strlen(szVersion) - 1] = '\0';
		fclose(hIni);
	}
	// if no specific version, no more search
	else
	{
		if( gs_p_oActionDLL )
			gs_p_oActionDLL -> OnQueryAction( this, C_uiUpdateAnimList, 0 );
		return;
	}

	char szVersion1[255];
	char szVersion2[255];
	char *szCut;
	int	 iNumVersion, iNbVersions = 1;

	strcpy(szVersion1, szVersion);
	szCut = strchr(szVersion1, ',');
	if (szCut)
	{
		strcpy(szVersion2, szCut+1 );
		strcpy(szCut, "\0");
		iNbVersions = 2;
	}

	for (iNumVersion = 0; iNumVersion < iNbVersions; iNumVersion++)
	{
		// build specific path
		strcpy(szPath, iNumVersion ? szVersion2 : szVersion1);
		strcat(szPath, strchr(fn_szGetAnimDataPath(), '\\'));
		
		// initialize searching loop (search all file in family directory)
		p_szName = szSearchName + sprintf( szSearchName, "%s\\%s\\", szPath, _p_oFamily->fn_p_szGetName() );
		strcpy( p_szName, "*.a3D" );
		hFD = FindFirstFile( szSearchName, &stWFD );

		// stop load if no file found or if an error occurs
		if ( hFD != INVALID_HANDLE_VALUE )
		{
			// save Loading World Mode
			bPreviousLoadingWorld = GetInterface() -> fn_bIsLoadingWorld();
			// no prefix added
			GetInterface() -> SetLoadingWorld( TRUE );

			do
			{
				strcpy( p_szName, stWFD.cFileName );
				// remove ".a3d" from name
				strcpy( szAnimName, stWFD.cFileName );
				if ( (p_cPoint = strrchr( szAnimName, '.' )) != NULL)
					*p_cPoint = 0;

				// get editor object
				p_oAnim = (CPA_Animation*)GetBaseObject( CString(szAnimName), C_szAnimationTypeName, _p_oFamily );
				// get engine object
				strcpy(szRealName, fn_szGetAnimDataPath());
				strcat(szRealName, szSearchName + strlen(szPath));
				p_xLVa = SCR_fnp_st_Link_SearchKey(p_stLK, szRealName);

				if (p_xLVa)
				{
					// engine exists, must have editor
					if( p_oAnim == NULL )
					{
						// editor object doesn't exist, create it
						p_oAnim = new CPA_Animation(this, _p_oFamily , szAnimName) ;
						// add animation to family
						_p_oFamily->mfn_vAddAnimation( p_oAnim );
					}
					// update engine
					if( ((struct tdstAnim3d_ *)p_oAnim -> GetData()) != ((struct tdstAnim3d_ *)SCR_M_ul_Link_GetValue( p_xLVa )) )
					{
						p_oAnim -> SetData( (struct tdstAnim3d_ *) SCR_M_ul_Link_GetValue( p_xLVa ) );
						p_oAnim -> SetAvailable( TRUE );
					}
				}
				else
				{
					// engine doesn't exist
					// create editor object only if complete load mode and doesn't already exist
					if( m_bCompleteLoad && ( p_oAnim == NULL ) )
					{
						// create editor animation

						p_oAnim = new CPA_Animation(this, _p_oFamily , szAnimName) ;
						// add animation in family
						_p_oFamily->mfn_vAddAnimation( p_oAnim );
						p_oAnim -> SetData( NULL );
						p_oAnim -> SetAvailable( FALSE );
					}
				}
			} while (FindNextFile( hFD, &stWFD) );

			// restore Loading World Mode
			GetInterface() -> SetLoadingWorld( bPreviousLoadingWorld );
			// close FindData handle
			FindClose(hFD);
		}
	}
//End Shaitan Correction Anims Specifiques }

	// 
	if( gs_p_oActionDLL )
		gs_p_oActionDLL -> OnQueryAction( this, C_uiUpdateAnimList, 0 );
}

/*
 *-----------------------------------------------------------------------------
 *  description : create all animations using link table
 *-----------------------------------------------------------------------------
 */
void TAnim_Interface::mfn_vCreateAllLoadedAnimations()
{
    SCR_tdst_Link_Table *p_stLK = fnp_stGetAnimationLinkTable();
    SCR_tdst_Link_Value *p_xLVa;
    unsigned int		 uiPos;
	char				 szSectionName[MAX_PATH];
	char				*szAnimName;
	char				*szFamilyName;
	char				*p_cPoint;
	unsigned int		 iAnimDataPathLength = strlen( fn_szGetAnimDataPath() ) + 1;
	CPA_Family			*p_oFamily = NULL;
	CPA_Animation		*p_oAnim;
    BOOL                 bPreviousLoadingWorld;

    // save Loading World Mode
    bPreviousLoadingWorld = GetInterface() -> fn_bIsLoadingWorld();
    // no prefix added
    GetInterface() -> SetLoadingWorld( TRUE );
	//
    uiPos = 0;
    SCR_M_DyAr_GetNextElement(SCR_tdst_Link_Value, uiPos, p_xLVa, SCR_M_st_Link_GetDynamicArray(p_stLK));
    while(p_xLVa)
    {
		strcpy( szSectionName, SCR_M_p_sz_Link_GetKey( p_xLVa ) );
		// get family name
		szFamilyName = szSectionName + iAnimDataPathLength;
		// get anim name
		szAnimName = strchr( szFamilyName, '\\' );
		*szAnimName = 0;
		szAnimName++;
        if ( (p_cPoint = strrchr( szAnimName, '.' )) != NULL)
	        *p_cPoint = 0;

		// search family
		if( ( p_oFamily == NULL ) || ( strcmp(szFamilyName, p_oFamily -> fn_p_szGetName() ) ) )
			p_oFamily = (CPA_Family*)gs_p_oFamilyDLL -> GetBaseObject( CString(szFamilyName), C_szFamilyTypeName );

		ASSERT( p_oFamily );

		// create animation
		p_oAnim = new CPA_Animation(this, p_oFamily , szAnimName) ;
		// add animation in family
		p_oFamily->mfn_vAddAnimation( p_oAnim );
		// set engine pointer
		p_oAnim -> SetData( (struct tdstAnim3d_ *) SCR_M_ul_Link_GetValue( p_xLVa ) );
		p_oAnim -> SetAvailable( TRUE );

		// next
        uiPos++;
        SCR_M_DyAr_GetNextElement(SCR_tdst_Link_Value, uiPos, p_xLVa, SCR_M_st_Link_GetDynamicArray(p_stLK));
    }
    // restore Loading World Mode
    GetInterface() -> SetLoadingWorld( bPreviousLoadingWorld );
}

/*
 *-----------------------------------------------------------------------------
 *  description : load preferences from .ini
 *-----------------------------------------------------------------------------
 */
void TAnim_Interface::mfn_vLoadPreferences()
{
    CString csFileName;
    char    szText[256];

    csFileName = M_GetMainApp()->m_csEditorDataPath + "Tools\\Anim\\Anim.ini";
    char *p_szFileName = (char*)(LPCSTR)csFileName;

    // CompleteLoad mode
    GetPrivateProfileString ("Preference", "Complete Load", "YES", szText, 256, p_szFileName);
    m_bCompleteLoad = !strcmpi( szText, "YES" );
}

/*
 *-----------------------------------------------------------------------------
 *  description : save preferences on .ini
 *-----------------------------------------------------------------------------
 */
void TAnim_Interface::mfn_vSavePreferences()
{
    CString csFileName;
	CString	csDimension;

    csFileName = M_GetMainApp()->m_csEditorDataPath + "Tools\\Anim\\Anim.ini";
    char *p_szFileName = (char*)(LPCSTR)csFileName;

    // CompleteLoad mode
    WritePrivateProfileString( "Preference", "Complete Load", m_bCompleteLoad ? "YES" : "NO" , p_szFileName );

    // write on file
    WritePrivateProfileString( NULL, NULL, NULL , p_szFileName );
}

