//	Zinc Application Framework - Z_STORE.HPP
//	COPYRIGHT (C) 1990-1999.  All Rights Reserved.
//	Zinc Software Incorporated.  Pleasant Grove, Utah  USA

#if !defined(Z_STORE_HPP)
#define Z_STORE_HPP
#include <z_dskfil.hpp>

// --------------------------------------------------------------------------
// ----- ZafStorage ---------------------------------------------------------
// --------------------------------------------------------------------------

/* START BLOCK COMMENT
**	class ZAF_EXPORT ZafStorageFunctorBody;
**	class ZAF_EXPORT ZafStorageFunctor
**	{
**	public:
**		ZafStorageFunctor();
**		ZafStorageFunctor(ZafStorageFunctorBody *body);
**		ZafStorageFunctor(const ZafStorageFunctor &copy);
**		~ZafStorageFunctor();
**		ZafStorageFunctor &operator=(ZafStorageFunctor &copy);
**	
**		operator void *();
**		void AssignBody(ZafStorageFunctorBody *body);
**		void Execute(const ZafIChar *string, ZafFileMode mode);
**	private:
**		ZafStorageFunctorBody *body;
**	};
**	
**	class ZafStorageFunctorBody
**	{
**	public:
**		ZafStorageFunctorBody();
**		virtual ~ZafStorageFunctorBody();
**	
**		int Count(void) const;
**		int DecrementCount(void);
**		int IncrementCount(void);
**		virtual void Execute(const ZafIChar *string, ZafFileMode mode) = 0;
**	
**	private:
**		int count;
**	};
END BLOCK COMMENT */

const ZafFileMode ZAF_FILE_DELETE	= 0x0100; // For callback purposes (used
															 // for RmDir and Remove).
const ZafFileMode ZAF_FILE_SAVE		= 0x0200; // For callback purposes (used
															 // for Save).

typedef ZafInt16 ZafVersion;

class ZAF_EXPORT ZafStorageFile;
class ZAF_EXPORT ZafDirectoryElement;

// --------------------------------------------------------------------------
// ----- ZafResource --------------------------------------------------------
// --------------------------------------------------------------------------

class ZafResource
{
public:
	ZafResource(unsigned char *data, int dataSize, ZafIChar *resourceName);
	virtual ~ZafResource();

	unsigned char* Data() {return data;}
	int DataSize() {return dataSize;}
	ZafIChar *ResourceName() {return resourceName;}

private:
	int dataSize; 
	unsigned char *data;
	ZafIChar *resourceName;

	// disallow assignment and copy construction

	ZafResource(const ZafResource &copy);
	ZafResource &operator=(const ZafResource &copy);
};

// --------------------------------------------------------------------------
// ----- ZafStorage ---------------------------------------------------------
// --------------------------------------------------------------------------

class ZAF_EXPORT ZafStorage : public ZafFileSystem
{
public:
	ZafStorage(void);
	ZafStorage(const ZafIChar *name, ZafFileMode mode = ZAF_FILE_READWRITE);
	ZafStorage(ZafResource &inMemoryStorage);
	virtual ~ZafStorage(void);

	// --- General Members ---
	int Save(int backups = 0);
	int SaveAs(const ZafIChar *newName, int backups = 0);

	// --- Data access ---
	// get
/* 	const ZafStorageFunctor &Callback(void) const; */
	ZafVersion Version(void) const;
	// set
/* 	ZafStorageFunctor &SetCallback(ZafStorageFunctor &callback); */
	ZafVersion SetVersion(ZafVersion version);

	// --- Modes ---
	bool Create(void) const;
	bool OpenCreate(void) const;
	bool ReadOnly(void) const;
	bool ReadWrite(void) const;

	// --- Directory Members ---
	virtual int ChDir(const ZafIChar *newPath,
		ZafStringID stringID = ZAF_NULLP(ZafIChar), ZafNumberID numberID = 0);
	virtual int FindFirst(ZafFileInfoStruct &fileInfo, const ZafIChar *searchName,
		ZafStringID stringID = ZAF_NULLP(ZafIChar), ZafNumberID numberID = 0);
	virtual int FindNext(ZafFileInfoStruct &fileInfo, const ZafIChar *searchName,
		ZafStringID stringID = ZAF_NULLP(ZafIChar), ZafNumberID numberID = 0);
	virtual int FindClose(ZafFileInfoStruct &fileInfo);
	virtual int GetCWD(ZafIChar *pathName, int pathLength);
	virtual int MkDir(const ZafIChar *pathName,
		ZafStringID stringID = ZAF_NULLP(ZafIChar), ZafNumberID numberID = 0);
	virtual int RmDir(const ZafIChar *pathName, bool deleteContents = false);

	// --- File Members ---
	virtual void Close(ZafFile *file);
	virtual ZafFile *Open(const ZafIChar *fileName, const ZafFileMode mode,
		ZafStringID stringID = ZAF_NULLP(ZafIChar), ZafNumberID numberID = 0);
	virtual int Remove(const ZafIChar *fileName);
	virtual int Rename(const ZafIChar *oldName, const ZafIChar *newName,
		ZafStringID stringID = ZAF_NULLP(ZafIChar), ZafNumberID numberID = 0);

protected:
	// --- Mode and Version info ---
	ZafFileMode mode;
	ZafVersion version;

	// --- File Access ---
//??? Only readFile is needed for readOnly mode.
//??? Should ZafStorageReadOnly be split out?
	ZafFile *readFile;
	ZafFile *tempFile;
	ZafFile *writeFile;

	// --- Disk Access ---
//??? Not needed for readOnly mode.
//??? Should ZafStorageReadOnly be split out?
	ZafDiskFileSystem diskFileSystem;
	ZafIChar *fileName;
	ZafIChar *tempFileName;

	// --- Directory Access ---
	ZafDirectoryElement *currentDirectory;
	ZafDirectoryElement *rootDirectory;

	// --- Directory Maintenance ---
	ZafDirectoryElement *WalkPath(const ZafIChar *path);
	ZafDirectoryElement *WalkPath(const ZafIChar *path, const ZafIChar **fileName);

	bool inMemStorage;  // flag indicates whether ZafStorage is on disk or in memory

	// --- Callback Mechanism ---
/* 	ZafStorageFunctor callback; */
};

// --- inline functions ---
inline bool ZafStorage::Create(void) const { return ((mode & ZAF_FILE_CREATE) ? true : false); }
inline bool ZafStorage::OpenCreate(void) const { return ((mode & ZAF_FILE_OPENCREATE) ? true : false); }
inline bool ZafStorage::ReadOnly(void) const { return ((mode & ZAF_FILE_READ) ? true : false); }
inline bool ZafStorage::ReadWrite(void) const { return ((mode & ZAF_FILE_READWRITE) ? true : false); }
inline ZafVersion ZafStorage::Version(void) const { return (version); }
inline ZafVersion ZafStorage::SetVersion(ZafVersion setVersion) { return (version = setVersion); }

// --------------------------------------------------------------------------
// ----- ZafStorageFile -----------------------------------------------------
// --------------------------------------------------------------------------

class ZAF_EXPORT ZafStorageFile : public ZafFile
{
	friend class ZAF_EXPORT ZafStorage;
public:
	// --- General Members ---
	bool Changed(void);
	const char *Data(void);

	// --- Search functions ---
	virtual ZafOffset Length(void) const;
	virtual int Seek(ZafOffset offset, ZafSeek location);
	virtual ZafOffset Tell(void) const;

	// --- I/O functions ---
	virtual int ReadData(void *buffer, int size);
	virtual int WriteData(const void *buffer, int size);

	// --- Accessors/Mutators ---
	bool Destroyable(void) const;
	virtual bool SetDestroyable(bool destroyable);

protected:
	// --- Data Management ---
	bool destroyable;
	bool changed;
	char *dataBuffer;
	ZafOffset bufferSize;
	ZafOffset length;
	ZafOffset position;

	// --- Directory Access ---
	ZafDirectoryElement *directoryElement;

	// Created and destroyed only by ZafStorage Open() and Close().
	ZafStorageFile(ZafFileMode mode, char *initData = ZAF_NULLP(char), int initDataSize = 0);
	virtual ~ZafStorageFile(void);
};

// --- inline functions ---
inline bool ZafStorageFile::Changed(void) { return (changed); }
inline const char *ZafStorageFile::Data(void) { return (dataBuffer); }
inline bool ZafStorageFile::Destroyable(void) const { return (destroyable); }

#endif // Z_STORE_HPP
