//---------------------------------------------------------------------------
//
// file.h - This file contains the class declaration for File
//
//				The File class simply calls the Windows 32bit file functions.
//				It is purely a wrapper.
//
//				The mmFile Class is a wrapper for the Win32 Memory Mapped
//				file functionality.  It is used exactly the same as above class.
//
//	Honor Bound -- FASA Interactive Technologies
//
//	Copyright (c) 1995 FASA Interactive Technologies
//
//
//---------------------------------------------------------------------------

#ifndef ABLFILE_H
#define ABLFILE_H
//---------------------------------------------------------------------------
// Include files

#pragma warning (disable:4284)
#pragma warning (push)
#include <stlport\string>
#pragma warning (pop)

#ifndef DSTD_H
//#include "dstd.h"
#endif

#ifndef DFILE_H
#include "dfile.h"
#endif

#ifndef DFFILE_H
//#include "dffile.h"
#endif

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
namespace ABL
{

//	extern std::string currentParamList;		// TODO: use this implementation or remove it
//	extern std::string currentScriptSuffix;

//---------------------------------------------------------------------------
// Enums
enum FileMode
{
	NOMODE = 0,
	READ,
	CREATE,
	APPEND,
	WRITE,
	RDWRITE
};

enum FileClass
{
	BASEFILE = 0,
	INIFILE,
	PACKETFILE
};

//---------------------------------------------------------------------------
// Function Declarations
bool fileExists(char *fName);

//---------------------------------------------------------------------------
// Macro Definitions
#ifndef	NO_ERR
#define	NO_ERR					0x00000000
#endif

#define	DISK_FULL_ERR			0xBADF0001
#define	SHARE_ERR				0xBADF0002
#define	FILE_NOT_FOUND_ERR		0xBADF0003
#define	PACKET_OUT_OF_RANGE		0xBADF0004
#define	PACKET_WRONG_SIZE		0xBADF0005
#define	READ_ONLY_ERR			0xBADF0006
#define	TOO_MANY_FILES_ERR		0xBADF0007
#define	READ_PAST_EOF_ERR		0xBADF0008
#define	INVALID_SEEK_ERR		0xBADF0009
#define	BAD_WRITE_ERR			0xBADF000A
#define	BAD_PACKET_VERSION		0xBADF000B
#define	NO_RAM_FOR_SEEK_TABLE	0xBADF000C
#define	NO_RAM_FOR_FILENAME		0xBADF000D
#define	PARENT_NULL				0xBADF000E
#define	TOO_MANY_CHILDREN		0xBADF000F
#define	FILE_NOT_OPEN			0xBADF0010
#define	CANT_WRITE_TO_CHILD		0xBADF0011
#define	NO_RAM_FOR_CHILD_LIST	0xBADF0012
#define MAPPED_WRITE_NOT_SUPPORTED	0xBADF0013
#define COULD_NOT_MAP_FILE		0xBADF0014

//---------------------------------------------------------------------------
//									File
//---------------------------------------------------------------------------
class File
{
	// Data Members
	//--------------
	protected:

		unsigned char *m_File;
		DWORD m_FileSize;
		DWORD m_FilePos;
	
		char 					*fileName;
	

	public:

	// Member Functions
	//------------------
		protected:

			void setup (void);

		public:

			File (void)
			{
				m_File = NULL;
				fileName = NULL;
				m_FileSize = m_FilePos = 0;
			}
			~File (void)
			{
				close ();
				m_File = NULL;
			}

			bool eof (void)
			{
				Verify (m_File);

				return (m_FilePos >= m_FileSize);
			}

			long open (char* fName, FileMode _mode = READ, long numChildren = 50)
			{

				long fNameLength = strlen(fName);
				
				fileName = (char *)new char[fNameLength+1];
				gosASSERT(fileName != NULL);
					
				strncpy(fileName,fName,fNameLength+1);

				if (m_File)
					close ();
				Verify (!m_File);
				gos_GetFile (fName,&m_File,&m_FileSize);

/*																// TODO: use this implementation or remove it
				if ((currentParamList.size() > 0) &&
					(strchr((const char*)m_File,'{') != 0))
				{
					std::string s((const char*)m_File);

					while ((currentParamList.size() > 0) &&
						   (s.find('{') != std::string::npos))
					{
						std::string::size_type left = s.find('{');
						std::string::size_type right = s.find('}');

						if ((right - left == 3) &&
							(s[left + 1] == '@') &&
							(s[left + 2] == '@'))
						{
							s.replace(left,right - left + 1,currentScriptSuffix);
						}
						else
						{
							std::string::size_type param_size = currentParamList.find(',');

							s.replace(left,right - left + 1,currentParamList,0,param_size);

							currentParamList.erase(0,param_size + 1);
						}
					}

					gos_Free(m_File);
					m_File = (unsigned char*)gos_Malloc(s.size() - 4);

					strncpy((char*)m_File,s.c_str(),s.size() - 4);

					m_FileSize = s.size() - 4;
				}
*/

				return NO_ERR;
			}
//			long open( char* buffer, int bufferLength ); // for streaming from memory

			long create (char* fName)
			{
				Verify (false);
				if (m_File)
					close ();
				return NO_ERR;
			}

			void close (void)
			{
				if (m_File)
				{
					gos_Free (m_File);
					m_File = NULL;
				}
				if (fileName)
				{
					delete[] fileName;
					fileName = NULL;
				}
			}

//			long open (File *_parent, unsigned long fileSize, long numChildren = 50);
			
			void deleteFile (void);

			long seek (long pos, long from = SEEK_SET)
			{
				if (!isOpen ())
					return 0;
				switch (from)
				{
					case SEEK_SET:
						m_FilePos = pos;
					break;
					case SEEK_CUR:
						m_FilePos += pos;
					break;
					case SEEK_END:
						m_FilePos = m_FileSize - pos;
					break;
				}
				Verify (m_FilePos >=0);
				if (m_FilePos > m_FileSize)
					m_FilePos = m_FileSize;
				return m_FilePos;
			}
			void seekEnd (void)
			{
				seek(0,SEEK_END);
			}
			void skip (long bytesToSkip)
			{
				if (bytesToSkip)
					seek(bytesToSkip,SEEK_CUR);
			}

			long read (unsigned long pos, MemoryPtr buffer, long length);
			long read (MemoryPtr buffer, long length);

			unsigned char readByte (void);
			short readWord (void);
			short readShort (void);
			long readLong (void);
			float readFloat( void );

			long readString (MemoryPtr buffer);
			long readLine (MemoryPtr buffer, long maxLength)
			{
				return readLineEx (buffer,maxLength);
			}
			long readLineEx (MemoryPtr buffer, long maxLength)
			{
				unsigned long read = 0;
				if (isOpen())
				{
					long pos;
					long i = 0;

					pos = getLogicalPosition ();

					read = maxLength;
					if ((m_FilePos+maxLength) > m_FileSize)
						read = m_FileSize - m_FilePos;
					memcpy (buffer,&(m_File[m_FilePos]),read);
					m_FilePos += read;
					if( maxLength > read )
						maxLength=read;
		
					while( i<maxLength && buffer[i]!='\n' )
						i++;
		
					i++;
					buffer[i++]=0;
		
					pos += (i-1);
		
					seek(pos);
				}
				else
				{
					return 0;
				}
				return read;
			}

			long write (unsigned long pos, MemoryPtr buffer, long bytes);
			long write (MemoryPtr buffer, long bytes);

			long writeByte (unsigned char value);
			long writeWord (short value);
			long writeShort (short value);
			long writeLong (long value);
			long writeFloat (float value);
			long writeString (char *buffer);
			long writeLine (char *buffer);

			bool isOpen (void)
			{
				return (m_File != NULL);
			}

			virtual FileClass getFileClass (void)
			{
				return BASEFILE;
			}

			char* getFilename (void)
			{
				return fileName;
			}

			unsigned long getLength (void)
			{
				if (!isOpen ())
					return 0;
				return m_FileSize;
			}
			unsigned long fileSize (void)
			{
				return getLength ();
			}
			unsigned long getNumLines (void)
			{
				unsigned long currentPos = getLogicalPosition ();
				unsigned long numLines = 0;
			
				seek(0);
				for (unsigned long i=0;i<getLength();i++)
				{
					unsigned char check1 = readByte();
					if (check1 == '\n')
						numLines++;
				}	
				
				seek(currentPos);
			
				return numLines;
			}

//			unsigned long getLastError (void);
			unsigned long getLogicalPosition (void)
			{
				return m_FilePos;
			}

			unsigned char* getData()
			{
				return (m_File);
			}
			
//			FilePtr getParent (void);
//			FileMode getFileMode (void);
//			long getFileHandle (void);

//			long getFileMTime (void);
			
//			long addChild (FilePtr child);
//			void removeChild (FilePtr child);

};

//---------------------------------------------------------------------------


}
//---------------------------------------------------------------------------
#endif

//---------------------------------------------------------------------------
//
// Edit Log
//
//
//---------------------------------------------------------------------------
