#ifndef __C4DFILE_H
#define __C4DFILE_H

#include "c4d_memory.h"
#include "ge_math.h"
#include "c4d_string.h"

class Filename;
class HyperFile;
class BaseContainer;
class BaseDocument;
class BaseBitmap;
class BaseChannel;

class Filename
{
	private:
		CHAR priv[28]; // fixed size of 28 bytes
	public:

		void* operator new(size_t,int line,const CHAR *file);
		void  operator delete(void *del);

		void* operator new(size_t,void *place) { return place; }
		void  operator delete(void*, void*) {}

		Filename(void);
		Filename(const String &string);
		Filename(const Filename &src);
		~Filename(void);

		Filename *GetClone(void) const;
		void CopyTo(Filename *dst) const;

		Bool FileSelect(LONG type=0, LONG flags=0, const String *title=NULL);
		
		Bool Content(void) const;

		String GetString(void) const;
		void SetString(const String &str);
		
		Filename GetDirectory(void) const;
		Filename GetFile(void) const;
		String GetFileString(void) const;
		
		void ClearSuffix(void);
		void SetSuffix(const String &str);
		Bool CheckSuffix(const String &str) const;

		void SetDirectory(const Filename &str);
		void SetFile(const Filename &str);

		const Filename& 			operator =  (const Filename &fname);
		friend const Filename	operator +  (const Filename &fname1,const Filename &fname2);
		const Filename&				operator += (const Filename &fname);
		Bool									operator == (const Filename &fname) const;
		Bool									operator != (const Filename &fname) const;
};

class BaseFile
{
	private:
		BaseFile(void);
	public:
		// Open a file, name is of type filename
		// mode					: read, write or readwrite
		// error_dialog	: display any errors in dialogs
		// order				:	little or big endian
		// type,creator	: MAC file types
		Bool Open(const Filename &name, LONG mode=GE_READ, LONG error_dialog=FILE_IGNOREOPEN, LONG order=GE_MOTOROLA, LONG type=MACTYPE_CINEMA, LONG creator=MACCREATOR_CINEMA);
		
		// Closes a file - automatically called when BaseFile is destructed
		Bool Close(void);	

		// Change byte order while reading - little or big endian allowed as parameter
		void SetOrder(LONG order);
		
		// Read len bytes
		LONG ReadBytes(void *data, LONG len, Bool just_try_it=FALSE);

		// Write len bytes
		Bool WriteBytes(void *data, LONG len);

		// Tries to read len bytes - if less bytes were read no error state is set
		// the number of read bytes is returned
		LONG TryReadBytes(void *data, LONG len);

		// Seek - returns error
		Bool Seek(LONG pos, LONG mode=GE_RELATIVE);
		
		// Return actual file position
		LONG GetPosition(void);

		// Return file length
		LONG GetLength(void);
		
		// Return file error
		LONG GetError(void);

		// Manually set file error
		void SetError(LONG error);  

		Bool ReadChar (CHAR  *v);
		Bool ReadUChar(UCHAR *v);
		Bool ReadWord (WORD  *v);
		Bool ReadUWord(UWORD *v);
		Bool ReadLong (LONG  *v);
		Bool ReadULong(ULONG *v);
		Bool ReadReal (Real  *v);
		Bool ReadLReal(LReal *v);
		Bool ReadFilename(Filename *v);
		Bool ReadBool(Bool *v);
		Bool ReadTime(BaseTime *v);
		Bool ReadVector(Vector *v);
		Bool ReadLVector(LVector *v);
		Bool ReadMatrix(Matrix *v);
		Bool ReadLMatrix(LMatrix *v);
		Bool ReadString(String *v);

		Bool WriteChar (CHAR  v);
		Bool WriteUChar(UCHAR v);
		Bool WriteWord (WORD  v);
		Bool WriteUWord(UWORD v);
		Bool WriteLong (LONG  v);
		Bool WriteULong(ULONG v);
		Bool WriteReal (Real  v);
		Bool WriteLReal(LReal v);
		Bool WriteFilename(const Filename &v);
		Bool WriteBool(Bool  v);
		Bool WriteTime(const BaseTime &v);
		Bool WriteVector(const Vector  &v);
		Bool WriteLVector(const LVector  &v);
		Bool WriteMatrix(const Matrix  &v);
		Bool WriteLMatrix(const LMatrix  &v);
		Bool WriteString(const String &v);

		static BaseFile *Alloc(void);
		static void Free(BaseFile *&fl);
};

class BrowseFiles
{
	private:
		BrowseFiles(void);
	public:
		void Init(const Filename &directory, Bool calcsize);
		Bool GetNext(void);		
		
		LONG GetSize(void);
		Bool IsDir(void);
		Filename GetFilename(void);

		static BrowseFiles *Alloc();
		static void Free(BrowseFiles *&bf);
};

class HyperFile
{
	private:
		HyperFile(void);
	public:
		Bool WriteChar(CHAR  v);
		Bool WriteUChar(UCHAR v);
		Bool WriteWord(WORD  v);
		Bool WriteUWord(UWORD v);
		Bool WriteLong(LONG  v);
		Bool WriteULong(ULONG v);
		Bool WriteReal(Real  v);
		Bool WriteLReal(LReal v);
		Bool WriteBool(Bool  v);
		Bool WriteTime(const BaseTime &v);
		Bool WriteVector(const Vector  &v);
		Bool WriteLVector(const LVector  &v);
		Bool WriteMatrix(const Matrix  &v);
		Bool WriteLMatrix(const LMatrix  &v);
		Bool WriteString(const String &v);
		Bool WriteFilename(const Filename &v);
		Bool WriteImage(BaseBitmap *v, LONG format, BaseContainer *data); 
		Bool WriteContainer(const BaseContainer &v);
		Bool WriteMemory(void *data, LONG count);
		Bool WriteChannel(BaseChannel *bc);

		Bool ReadChar(CHAR *v);
		Bool ReadUChar(UCHAR *v);
		Bool ReadWord(WORD *v);
		Bool ReadUWord(UWORD *v);
		Bool ReadLong(LONG *v);
		Bool ReadULong(ULONG *v);
		Bool ReadReal(Real *v);
		Bool ReadLReal(LReal *v);
		Bool ReadBool(Bool *v);
		Bool ReadTime(BaseTime *v);
		Bool ReadVector(Vector *v);
		Bool ReadLVector(LVector *v);
		Bool ReadMatrix(Matrix *v);
		Bool ReadLMatrix(LMatrix *v);
		Bool ReadString(String *v);
		Bool ReadFilename(Filename *v);
		Bool ReadImage(BaseBitmap *v);
		Bool ReadContainer(BaseContainer *v, Bool flush);
		Bool ReadMemory(void **data, LONG *size);
		Bool ReadChannel(BaseChannel *bc);

		LONG GetError(void);
		void SetError(LONG err);
		Bool ReadValueHeader(UCHAR *h);
		Bool SkipValue(UCHAR h); 
		Bool WriteChunkStart(LONG id, LONG level);
		Bool WriteChunkEnd(void);
		Bool ReadChunkStart(LONG *id, LONG *level);
		Bool ReadChunkEnd(void);
		Bool SkipToEndChunk(void); 

		LONG GetFileVersion(void);

		BaseDocument *GetDocument(void);
};

LONG ReadHyperFile(BaseDocument *doc, GeListNode *node, const Filename &filename, LONG ident, String *warning_string);
LONG WriteHyperFile(BaseDocument *doc, GeListNode *node, const Filename &filename, LONG ident);

Bool GeFExist    (const Filename &name, Bool isdir=FALSE);
Bool GeSearchFile(const Filename &directory, const Filename &name, Filename *found);
Bool GeFKill     (const Filename &name, Bool isdir=FALSE);
Bool GeFCopyFile (const Filename &source, const Filename &dest, Bool overwrite);
Bool GeFRename   (const Filename &source, const Filename &dest);
Bool GeFCreateDir(const Filename &name);
Bool GeExecuteFile(const Filename &path);
Bool GeExecuteProgram(const Filename &program, const Filename &file);
Filename GeGetStartupPath(void);
Filename GeGetPluginPath(void);

void FreeFilename(Filename *&fn);

#endif
