/////////////////////////////////////////////////////////////
// CINEMA 4D SDK                                           //
/////////////////////////////////////////////////////////////
// (c) 1989-2004 MAXON Computer GmbH, all rights reserved  //
/////////////////////////////////////////////////////////////

#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 MemoryFileStruct
{
	private:
		MemoryFileStruct();
		~MemoryFileStruct();
	public:
		static MemoryFileStruct* Alloc();
		static void Free(MemoryFileStruct *&mfs);

		void GetData(void *&data, VLONG &size, Bool release = FALSE);
};

class Filename
{
	private:
#if defined __C4D_64BIT
		CHAR priv[48]; // fixed size of 48 bytes
#else
		CHAR priv[28]; // fixed size of 28 bytes
#endif
	public:

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

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

		Filename(void);
		Filename(const CHAR *string);
		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);

		void SetMemoryReadMode(void *adr, VLONG size = -1);
		void SetMemoryWriteMode(MemoryFileStruct *mfs);

		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();
		~BaseFile();
	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
		VLONG ReadBytes(void *data, VLONG len, Bool just_try_it=FALSE);

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

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

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

		// Return file length
		VLONG 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 ReadLLong(LLONG *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 WriteLLong(LLONG 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 LocalFileTime
{
	public:
		UWORD	year;
		UWORD	month;
		UWORD	day;
		UWORD	hour;
		UWORD	minute;
		UWORD	second;

	void Init(void)
	{
		year=month=day=hour=minute=second=0;
	}

	// > 0: t0 > t1
	// = 0: t0 == t1
	// < 0: t0 < t1
	LONG	Compare( const LocalFileTime &t0, const LocalFileTime &t1 )
	{
		LONG	result;
		
		result = t0.year - t1.year;
		if ( result == 0 )
		{
			result = t0.month - t1.month;
			if ( result == 0 )
			{
				result = t0.day - t1.day;
				if ( result == 0 )
				{
					result = t0.hour - t1.hour;
					if ( result == 0 )
					{
						result = t0.minute - t1.minute;
						if ( result == 0 )
							result = t0.second - t1.second;
					}
				}
			}
		}
		return( result );
	}

	Bool operator == (const LocalFileTime &x)
	{
		return year==x.year && month==x.month && day==x.day && hour==x.hour && minute==x.minute && second==x.second;
	}

	Bool operator != (const LocalFileTime &x)
	{
		return year!=x.year || month!=x.month || day!=x.day || hour!=x.hour || minute!=x.minute || second!=x.second;
	}

	Bool operator > (const LocalFileTime &x)
	{
		return( Compare( *this, x ) > 0 );
	}

	Bool operator < (const LocalFileTime &x)
	{
		return( Compare( *this, x ) < 0 );
	}

	Bool operator >= (const LocalFileTime &x)
	{
		return( Compare( *this, x ) >= 0 );
	}

	Bool operator <= (const LocalFileTime &x)
	{
		return( Compare( *this, x ) <= 0 );
	}
};

#define	GE_FILETIME_CREATED		0
#define	GE_FILETIME_MODIFIED	1
#define	GE_FILETIME_ACCESS		2

#define BROWSEFILES_CALCSIZE				(1<<0)
#define BROWSEFILES_SUPPRESSCACHING	(1<<1)

class BrowseFiles
{
	private:
		BrowseFiles();
		~BrowseFiles();
	public:
		void Init(const Filename &directory, LONG flags);
		Bool GetNext(void);		
		
		VLONG GetSize(void);
		Bool IsDir(void);
		Bool IsHidden(void);
		Bool IsBundle(void);
		Bool IsReadOnly(void);

		void GetFileTime(LONG mode, LocalFileTime *out);

		Filename GetFilename(void);

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

#define BROWSEVOLUMES_VOLUME_NOT_AVAILABLE		( 1 << 7 )

class BrowseVolumes
{
	private:
		BrowseVolumes();
		~BrowseVolumes();
	public:
		void Init(void);
		Bool GetNext(void);		
		Filename	GetFilename(void);
		String		GetVolumeName( LONG *out_flags );

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

class HyperFile
{
	private:
		HyperFile();
		~HyperFile();
	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 WriteLLong(LLONG 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, LONG savebits=SAVEBIT_ALPHA); 
		Bool WriteGeData(const GeData &v);
		Bool WriteContainer(const BaseContainer &v);
		Bool WriteMemory(void *data, VLONG 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 ReadLLong(LLONG *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 ReadGeData(GeData *v);
		Bool ReadContainer(BaseContainer *v, Bool flush);
		Bool ReadMemory(void **data, VLONG *size);
		Bool ReadChannel(BaseChannel *bc);
		Bool ReadChannelConvert(GeListNode *node, LONG link_id);

		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);

		static HyperFile *Alloc(void);
		static void Free(HyperFile *&fl);
		Bool Open(const Filename &filename, LONG mode, LONG ident);
		Bool Close();
};

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);

#define	GE_FKILL_DIRECTORY	1
#define	GE_FKILL_RECURSIVE	2

Bool GeFExist    (const Filename &name, Bool isdir=FALSE);
Bool GeSearchFile(const Filename &directory, const Filename &name, Filename *found);
Bool GeFKill     (const Filename &name, LONG flags=0);
Bool GeFCopyFile (const Filename &source, const Filename &dest, Bool overwrite);
Bool GeFRename   (const Filename &source, const Filename &dest);
Bool GeFMove     (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 GeGetStartupWritePath(void);
Filename GeGetPluginPath(void);

#define C4D_PATH_PREFS					1	// c4d prefs directory
#define C4D_PATH_RESOURCE				2	// c4d resource directory
#define C4D_PATH_LIBRARY				3	// c4d library (built-in)
#define C4D_PATH_LIBRARY_USER		4 // c4d library (different if multiuser mode enabled)
#define C4D_PATH_ONLINE_HELP		5 // c4d online help directory 
#define C4D_PATH_DESKTOP				6 // OS desktop directory
#define C4D_PATH_HOME						7 // OS home directory
#define C4D_PATH_STARTUPWRITE		8 // Writeable StartupDir!

Filename GeGetC4DPath(LONG whichpath);

Bool GeGetFileTime(const Filename &name, LONG mode, LocalFileTime *out);
Bool GeSetFileTime(const Filename &name, LONG mode, const LocalFileTime *in);
void GeGetCurrentTime(LocalFileTime *out);

void FreeFilename(Filename *&fn);

String DateToString(const LocalFileTime &t, Bool date_only);
Bool ShowInFinder(const Filename &fn, Bool open);

#endif
