/*
 =======================================================================================
  Name        :IniData.cpp
 
  Author      : VL                          Date :16/07/97
 
  Description :function to get ini data, check this data, write them ...
 =======================================================================================
  Modification -> Author :                  Date :
  Description :
 =======================================================================================
 */

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#include "stdafx.h"

#include <io.h>
#include <sys/stat.H>

#include "constant.h"
#include "IniData.h"
#include "Tree_Fct.h"
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

/*
 =======================================================================================
  Globals
 =======================================================================================
 */

tdstWindowsPref	g_stWinPref;
tdstIniData		g_stIniData;			// data in ini file
tdstIniData		g_stDefaultData =		// default value for data
				{
					"X:\\CPA\\Exe\\Main\\Gamedata",
					"X:\\CPA\\Exe\\Main\\",
					0,
					"chkData.log",
					"SectType.txt",
					0,
					{ "CheckFileList", -1, "NoFileListConfig", "", 0, NULL },
					{
						"GameData\\World\\Graphics\\Textures",
						"GameData",
						"GameData\\World",
						"GameData\\World\\Levels",
						"GameData\\World\\Levels\\_Common\\Families",
						"GameData\\World\\Levels",
						"GameData\\World\\Graphics\\Anims",
						"GameData\\World\\Graphics\\Objects\\Classes",
						"GameData\\World\\Graphics\\Objects\\Banks",
						"GameData\\World\\Libraries\\Mechanics",
						"GameData\\World\\Sound",
						"GameData\\World\\Graphics\\Visuals",
						"GameData\\World\\Libraries\\Materials",
						"GameData\\World\\Libraries\\Environment",
						"GameData\\SaveGame",
						"GameData\\Vignette",
						"GameData\\Options",
						"GameData\\World\\Levels"
					},
					18,
					{
						{g_stIniData.stAvailablePaths.szGraphicsBanks, "GraphicsBanks"},
						{g_stIniData.stAvailablePaths.szLevels, "Levels"},
						{g_stIniData.stAvailablePaths.szFamilies, "Families"},
						{g_stIniData.stAvailablePaths.szTexture, "Texture" } ,
						{g_stIniData.stAvailablePaths.szGameData, "GameData"} ,
						{g_stIniData.stAvailablePaths.szWorld, "World"},
						{g_stIniData.stAvailablePaths.szCharacters, "Characters"},
						{g_stIniData.stAvailablePaths.szAnimations, "Animations"},
						{g_stIniData.stAvailablePaths.szGraphicsClasses, "GraphicsClasses"},
						{g_stIniData.stAvailablePaths.szMechanics, "Mechanics"},
						{g_stIniData.stAvailablePaths.szSound, "Sound"},
						{g_stIniData.stAvailablePaths.szVisuals, "Visuals"},
						{g_stIniData.stAvailablePaths.szMaterials, "Materials"},
						{g_stIniData.stAvailablePaths.szEnvironment, "Environment"},
						{g_stIniData.stAvailablePaths.szSaveGame, "SaveGame"},
						{g_stIniData.stAvailablePaths.szVignettes, "Vignettes"},
						{g_stIniData.stAvailablePaths.szOptions, "Options"},
						{g_stIniData.stAvailablePaths.szZdx, "Zdx"}
					}
				};

char			g_szIniFile[MAX_PATH];

/*
 =======================================================================================
	Macros 
 =======================================================================================
 */

/*
 * Macro to bound size of a rect
 */
#define M_vCheckRectSize( _p_stRect, _iMinWidth, _iMinHeight )\
{\
	if (_p_stRect->right - _p_stRect->left + 1 < _iMinWidth )\
		_p_stRect->right = _p_stRect->left + _iMinWidth ;\
	if (_p_stRect->bottom - _p_stRect->top + 1 < _iMinHeight )\
		_p_stRect->bottom = _p_stRect->top + _iMinHeight;\
}

/*
 =======================================================================================
  Functions to manage file list
 =======================================================================================
 */

/*
 ----------------------------------------------------------------------------------------
  Description   : free fileList in Init Data structure
 ----------------------------------------------------------------------------------------
 */
void fn_IniD_vFreeFileList( tdstFileListConfig *_p_stFileList )
{
	int iFile;

	if ( _p_stFileList == NULL)
		return;
	
	if (_p_stFileList->lNumberOfFiles != 0)
	{
		for (iFile = 0; iFile < _p_stFileList->lNumberOfFiles; iFile++)
			free ( _p_stFileList->d_szFile[iFile] );
		free ( _p_stFileList->d_szFile );
		_p_stFileList->lNumberOfFiles = 0;
	}
}


/*
 ----------------------------------------------------------------------------------------
  Description   : write file list config in ini file
 ----------------------------------------------------------------------------------------
 */
void fn_IniD_vWriteFileList( tdstFileListConfig *_p_stFileList )
{
	int					iOldFileNumber;
	int					iFile;
	char				szString[40];


	if (_p_stFileList == NULL)
		return;

	/* set ini file in RW mode if in ReadOnly mode */
	if (_access( g_szIniFile, 2) == -1)
		_chmod ( g_szIniFile, _S_IWRITE );

	iOldFileNumber = GetPrivateProfileInt( _p_stFileList->szId, "Number", 0, g_szIniFile );
	if ( iOldFileNumber == 0 ) // new config
		g_stIniData.cNumberOfConfigs++;

	WritePrivateProfileString( "Vss", _p_stFileList->szKey, _p_stFileList->szId, g_szIniFile );
	WritePrivateProfileString( _p_stFileList->szId, "Name", _p_stFileList->szName, g_szIniFile );
	WritePrivateProfileString( _p_stFileList->szId, "Number", itoa( _p_stFileList->lNumberOfFiles, szString, 10 ), g_szIniFile );

	for ( iFile = 0; iFile < _p_stFileList->lNumberOfFiles; iFile ++)
	{
		sprintf( szString, "File%04d", iFile );
		WritePrivateProfileString( _p_stFileList->szId, szString, _p_stFileList->d_szFile[iFile], g_szIniFile );
	}
	for ( ;iFile < iOldFileNumber; iFile ++)
	{
		sprintf( szString, "File%04d", iFile );
		WritePrivateProfileString( _p_stFileList->szId, szString, NULL, g_szIniFile );
	}
}

/*
 ----------------------------------------------------------------------------------------
  Description   : get file list config from ini file
 ----------------------------------------------------------------------------------------
 */
BOOL fn_IniD_bGetFileList( tdstFileListConfig *_p_stFileList, char _cConfig )
{
	long				lNbFiles;
	int					iFile;
	int					iDeleteFile;
	char				szKey[10];
	char				**d_szFileName;

	if (_p_stFileList == NULL)
		return FALSE;

	if ( (_cConfig < 0) || (_cConfig >= g_stIniData.cNumberOfConfigs) )
		return FALSE;

	sprintf( _p_stFileList->szId, "FileList-Config%02d", _cConfig );

	/* get config name */
	GetPrivateProfileString( _p_stFileList->szId, "Name", "No name", _p_stFileList->szName, 40, g_szIniFile);
	/* get number of file */
	lNbFiles = GetPrivateProfileInt( _p_stFileList->szId, "Number", 0, g_szIniFile);
	if (lNbFiles == 0)
		return FALSE;

	/* allocate memory for pointer to file names */
	d_szFileName = (char **) malloc ( lNbFiles * sizeof( char *) );
	/* get each file name */
	for (iFile = 0; iFile < lNbFiles; iFile ++)
	{
		d_szFileName[iFile] = (char *) malloc( _MAX_PATH );
		sprintf( szKey, "File%04d", iFile );
		GetPrivateProfileString( _p_stFileList->szId, szKey, "Error", d_szFileName[iFile], MAX_PATH, g_szIniFile );
		if (strcmp( d_szFileName[iFile], "Error") == 0)
		{
			for (iDeleteFile = 0; iDeleteFile <= iFile; iDeleteFile ++)
				free ( d_szFileName[iDeleteFile] );
			free (d_szFileName);
			return FALSE;
		}
	}
	
	/* update ini data */
	fn_IniD_vFreeFileList( _p_stFileList );
	_p_stFileList->lNumberOfFiles = lNbFiles;
	_p_stFileList->d_szFile = d_szFileName;

	return TRUE;
}

/*
 ----------------------------------------------------------------------------------------
  Set file list to default value
 ----------------------------------------------------------------------------------------
 */
void fn_IniD_vSetSingleFileList( tdstFileListConfig *_p_stFileList, char *_szFileName )
{
	if ( _p_stFileList == NULL )
		return;

	fn_IniD_vFreeFileList( _p_stFileList );
	_p_stFileList->lNumberOfFiles = 1;
	_p_stFileList->d_szFile = (char **) malloc( sizeof( char *) );
	_p_stFileList->d_szFile[0] = (char *) malloc( MAX_PATH );
	sprintf( _p_stFileList->d_szFile[0], "-R %s", _szFileName );
}



/*
 ----------------------------------------------------------------------------------------
  Description   : get index of a config from id of the config
  _szId               -> string id of config
  Returns (char ) index of config (-1 if not a valid string id
 ----------------------------------------------------------------------------------------
 */
char fn_IniD_cGetIndexFromId( char *_szId )
{
	if ( strlen( _szId ) != 17 )
		return -1;

	if ( strncmp( _szId, "FileList-Config", 15 ) != 0)
		return -1;

	if ( !isdigit( _szId[15] ) || !isdigit( _szId[16] ) )
		return -1;

	return (_szId[15] - '0') * 10 + (_szId[16] - '0');
}

/*
 ----------------------------------------------------------------------------------------
  get number of file list config
 ----------------------------------------------------------------------------------------
 */
char fn_IniD_cGetNumberOfConfig( void )
{
	return g_stIniData.cNumberOfConfigs;
}

/*
 ----------------------------------------------------------------------------------------
  get name of a config
 ----------------------------------------------------------------------------------------
 */
void fn_IniD_vGetConfigName( char _cConfig, char *_szName )
{
	char szConfigId[20];
	sprintf( szConfigId, "FileList-Config%02d", _cConfig );
	GetPrivateProfileString( szConfigId, "Name", "Error", _szName, 40, g_szIniFile );
}

/*
 =======================================================================================
  function to get/set single initial data
 =======================================================================================
 */

/*
 ----------------------------------------------------------------------------------------
  Get extensions status
 ----------------------------------------------------------------------------------------
 */
BOOL fn_IniD_bGetFileTypeConsiderStatus( char *_szExt )
{
	int iResult;
	
	iResult = GetPrivateProfileInt( "FileType", _szExt, 1, g_szIniFile );
	return (iResult == 1);
}

/*
 ----------------------------------------------------------------------------------------
  Set extensions status
 ----------------------------------------------------------------------------------------
 */
void fn_IniD_vSetFileTypeConsiderStatus( char *_szExt, BOOL _bConsider )
{
	/* set ini file in RW mode if in ReadOnly mode */
	if (_access( g_szIniFile, 2) == -1)
		_chmod ( g_szIniFile, _S_IWRITE );

	WritePrivateProfileString( "FileType", _szExt, _bConsider ? "1" : "0", g_szIniFile );
}

/*
 ----------------------------------------------------------------------------------------
  set local path in ini file
 ----------------------------------------------------------------------------------------
 */
void fn_IniD_vSetLocalPath( char *_szPath )
{
	/* set ini file in RW mode if in ReadOnly mode */
	if (_access( g_szIniFile, 2) == -1)
		_chmod ( g_szIniFile, _S_IWRITE );

	WritePrivateProfileString( "Local", "DataRootPath", _szPath, g_szIniFile );
}

/*
 ----------------------------------------------------------------------------------------
  set result file name
 ----------------------------------------------------------------------------------------
 */
void fn_IniD_vSetModifListFile( char *_szFileName )
{
	/* set ini file in RW mode if in ReadOnly mode */
	if (_access( g_szIniFile, 2) == -1)
		_chmod ( g_szIniFile, _S_IWRITE );

	WritePrivateProfileString( "Result", "File", _szFileName, g_szIniFile );
}


/*
 ----------------------------------------------------------------------------------------
  Analyse string that describe a rect
 ----------------------------------------------------------------------------------------
 */
void fn_IniD_vAnalyseRectData( char *_szString, RECT *_p_stRect )
{
	char *p_szValue[5],  *p_szEnd;
	char cVal;

	memset( _p_stRect, 0, sizeof( RECT ) );

	if ( (p_szValue[0] = strchr(_szString, '(' )) == NULL)
		return;

	if ( (p_szValue[1] = strchr (++p_szValue[0], ',')) == NULL)
		return;
	if ( (p_szValue[2] = strchr (++p_szValue[1], ',')) == NULL)
		return;
	if ( (p_szValue[3] = strchr (++p_szValue[2], ',')) == NULL)
		return;
	p_szValue[3] ++;

	p_szValue[4] = _szString + strlen( _szString );

	for (cVal = 0; cVal < 4; cVal ++)
	{
		while ( !isdigit(*p_szValue[cVal]) )
		{
			if (p_szValue[cVal] == p_szValue[cVal+1])
				return;
			p_szValue[cVal]++;
		}
		p_szEnd = p_szValue[cVal] + 1;
		while ( isdigit(*p_szEnd))
		{
			if (p_szEnd == p_szValue[cVal+1])
				return;
			p_szEnd++;
		}
		*p_szEnd = 0;
	}

	_p_stRect->left   = atoi( p_szValue[0] );
	_p_stRect->top    = atoi( p_szValue[1] );
	_p_stRect->right  = atoi( p_szValue[2] );
	_p_stRect->bottom = atoi( p_szValue[3] );
}


/*
 =======================================================================================
	function for windows preference data 
 =======================================================================================
 */
/*
 ----------------------------------------------------------------------------------------
  Description   : get position and size of windows
 ----------------------------------------------------------------------------------------
 */
void fn_IniD_vGetWindowPreference( void )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	char szString[100];
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

	/* main window */
	GetPrivateProfileString( "WinPref", "Main", "", szString, 100, g_szIniFile );
	fn_IniD_vAnalyseRectData( szString, &g_stWinPref.stMainPos );
	M_vCheckRectSize( (&g_stWinPref.stMainPos), C_iMainMinWidth, C_iMainMinHeight );
}

/*
 ----------------------------------------------------------------------------------------
  Description   : write position and size of windows
 ----------------------------------------------------------------------------------------
 */
void fn_IniD_vWriteWindowPreference( void )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	char szValue[50];
	RECT *p_stRect;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

	/* set ini file in RW mode if in ReadOnly mode */
	if (_access( g_szIniFile, 2) == -1)
		_chmod ( g_szIniFile, _S_IWRITE );

	/* main window */
	p_stRect = &g_stWinPref.stMainPos;
	sprintf( szValue, "(%4d,%4d,%4d,%4d)", p_stRect->left, p_stRect->top, p_stRect->right, p_stRect->bottom );
	WritePrivateProfileString( "WinPref", "Main    ", szValue, g_szIniFile );
}



/*
 *=======================================================================================
 * function for all initial data
 *=======================================================================================
 */

/*
 ----------------------------------------------------------------------------------------
  transform ini file to keep file compatible
 ----------------------------------------------------------------------------------------
 */
void fn_IniD_vTransformIniFileToBeCompatible( void )
{
}

/*
 ----------------------------------------------------------------------------------------
  Description   : read ini data to fill inidata structure
					and set additional ini data
  _bFirst             -> indicate that it's the first initialisation
 ----------------------------------------------------------------------------------------
 */
void fn_IniD_vGetAllFromIniFile( BOOL _bFirst )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	char				szConfigId[20];
	char				szConfigName[40];
	tdstFileListConfig	*p_stConfig;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	
	if (_bFirst)
	{
		/*
		 * transform eventually ini file
		 */
		fn_IniD_vTransformIniFileToBeCompatible();
		/*
		 * Build ini file
		 */
		GetCurrentDirectory( MAX_PATH, g_szIniFile );
		if (g_szIniFile[strlen(g_szIniFile) - 1] != '\\')
			strcat( g_szIniFile, "\\");
		strcat( g_szIniFile, C_szIniFile );

		memcpy ( &g_stIniData, &g_stDefaultData, sizeof( tdstIniData ) ); 
		memset ( &g_stWinPref, 0, sizeof( tdstWindowsPref ) );
		
		fn_IniD_vGetWindowPreference();

		/* retrieve number of config */
		g_stIniData.cNumberOfConfigs = 0;
		while (1)
		{
			sprintf( szConfigId, "FileList-Config%02d", g_stIniData.cNumberOfConfigs);
			GetPrivateProfileString( szConfigId, "Name", "Error", szConfigName, 40, g_szIniFile );
			if (strcmp(szConfigName, "Error") == 0)
				break;
			g_stIniData.cNumberOfConfigs++;
		}

	}

	GetPrivateProfileString( "Local", "DataRootPath", g_stDefaultData.szLocalPath, g_stIniData.szLocalPath, MAX_PATH, g_szIniFile );
	GetPrivateProfileString( "Local", "RootForSection", g_stDefaultData.szRootForSection, g_stIniData.szRootForSection, MAX_PATH, g_szIniFile );
	g_stIniData.lRootForSectionLength = strlen( g_stIniData.szRootForSection );
	GetPrivateProfileString( "Result", "File", g_stDefaultData.szResultFile, g_stIniData.szResultFile, MAX_PATH, g_szIniFile );

	/*
	 * get check file list Id
	 */
	p_stConfig = &g_stIniData.stCheckConfig;
	GetPrivateProfileString( "Vss", p_stConfig->szKey, g_stDefaultData.stCheckConfig.szId, p_stConfig->szId, 20, g_szIniFile );
	p_stConfig->cIndex = fn_IniD_cGetIndexFromId( p_stConfig->szId );
	if (p_stConfig->cIndex != -1)
		fn_IniD_bGetFileList( p_stConfig, p_stConfig->cIndex );
	else
		fn_IniD_vSetSingleFileList( p_stConfig, g_stIniData.szLocalPath + g_stIniData.lRootForSectionLength );
}
