#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef __TOOLS_MODEDATAFILE_H_
#define __TOOLS_MODEDATAFILE_H_


#include "Core/Asura_Windows.h"

/*
Base class for a crude data file containing stuff that should be saved out about a given
tools mode
Version handling is done simply by tacking things on the end. (when reading it reads in as much
as it can , and then leaves the rest as default values)

Added a version number (defaults to 0) that may need to be incremented if changes are made that
would make old files obsolete.
Since these files aren't that critical it is just been put in at the moment to prevent junk data
from being read in , so if a file with a different version number is found , it will be ignored.
However I may well change this when it actually becomes necessary to use this.

*/

/*
Changed version number so contents is only discarded if the file is newer than can be dealt with. Otherwise , the version
loaded can be dealt with by checking GetVersion().
RAR 06/03/2007
*/



#define TOOLSMODEDATAFILE_LOAD 0 
#define TOOLSMODEDATAFILE_SAVE 1

class Tools_ModeDataFile
{
	public :
		enum FileMode { Loading, Saving };
		
		//opens the file for loading/saving. a path does not need to be given
		Tools_ModeDataFile( const char* szFilename, int iMode, int iVersion = 0, const char* szPath = NULL);
		~Tools_ModeDataFile();

		//loads/saves data in the file. when loading the data is left unchanged if it failed to read anything
		//(as would happen if the file end had been reached)
		template<class T> bool Transfer(T& data)
		{
			return Transfer( &data, sizeof(data) );
		}
        template<> bool Transfer(Asura_String& xDataString)
        {
            if ( m_iMode == TOOLSMODEDATAFILE_LOAD )
            {
                u_int uStringLength;
                bool bOk = Transfer( uStringLength );
                // Check that the length is sensible before reading the string.
                if ( bOk && uStringLength < m_uLoadFileSize )
                {
                    if ( uStringLength == 0 )
                    {
                        xDataString.MakeNull();
                    }
                    else
                    {
                        char* pszString = new char[ uStringLength + 1 ];
                        bOk = Transfer( pszString, uStringLength );
                        if ( bOk )
                        {
                            pszString[ uStringLength ] = '\0';
                            xDataString = pszString;
                        }
                        delete [] pszString;
                    }
                }
                return bOk;
            }
            else
            {
                u_int uStringLength = static_cast< u_int >( xDataString.GetLength() );
                const bool bOk = Transfer( uStringLength );
                return bOk && Transfer( xDataString.GetString(), xDataString.GetLength() );
            }
        }

		bool Transfer( void* vData, unsigned uData_size );

		bool GetError()         { return m_bHadAnError; }
		int  GetVersion() const { return m_iCurrentVersion; }
		int  GetMode()    const { return m_iMode; }

	private	:	
		int				m_iMode;		
		int				m_iCurrentVersion;
		HANDLE			m_xFileHandle;
        DWORD           m_uLoadFileSize;
		bool			m_bHadAnError;			//set to true after a failed read/write... not much point in continuing after that
		void*			m_pvBuffer;
		unsigned		m_uBufferSize;
};


#endif //__TOOLS_MODEDATAFILE_H_
