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

#if !defined(Z_DATA_HPP)
#define Z_DATA_HPP
#include <z_list.hpp>
#include <z_file.hpp>
#include <z_notify.hpp>
#include <z_event.hpp>

// --------------------------------------------------------------------------
// ----- ZafDataPersistence -------------------------------------------------
// --------------------------------------------------------------------------

#if defined(USE_ZAF_PERSISTENCE)
class ZAF_EXPORT ZafDataPersistence;
typedef ZafElement *(*ZafDataConstructor)(const ZafIChar *, ZafDataPersistence &);

enum ZafPersistEntryType
{
	ZAF_PERSIST_ROOT_DIRECTORY,
	ZAF_PERSIST_ROOT_FILE,
	ZAF_PERSIST_DIRECTORY,
	ZAF_PERSIST_FILE,
	ZAF_PERSIST_DATA
};

const int ZAF_MAXFILES							= 40;

class ZAF_EXPORT ZafDataPersistence
{
public:
	// --- Data constructors ---
	struct DataConstructor
	{
		ZafClassID classID;
		ZafClassName className;
		ZafDataConstructor constructor;
	};

	// --- General members ---
	ZafDataPersistence(ZafFileSystem *fileSystem, DataConstructor *dataConstructor);
	ZafDataPersistence(const DataConstructor &copy);
	ZafDataPersistence(const ZafDataPersistence &copy);
	virtual ~ZafDataPersistence(void);

	ZafError AllocateFile(const ZafIChar *name, ZafFileMode mode);
	ZafDataPersistence &PopLevel(void);
	ZafDataPersistence &PushLevel(ZafClassName className, ZafClassID classID, ZafPersistEntryType type);

	virtual DataConstructor *AddDataConstructor(ZafClassName className, ZafClassID classID, ZafDataConstructor constructor);
	ZafFileSystem *AddFileSystem(ZafFileSystem *fileSystem, ZafFileSystem *position = ZAF_NULLP(ZafFileSystem));
	virtual void ClearDataConstructors(void);
	virtual void ClearFileSystems(void);
	virtual ZafDataConstructor GetDataConstructor(ZafClassID classID, ZafClassName className = 0);
	bool Merge(ZafDataPersistence &copy);
	virtual bool SetDataConstructors(DataConstructor *dataConstructor);
	virtual bool SubtractDataConstructor(ZafClassID classID, ZafClassName className = 0);
	ZafFileSystem *SubtractFileSystem(ZafFileSystem *fileSystem);

	ZafFile *CurrentFile(void) const;
	ZafFileSystem *CurrentFileSystem(void) const;
	ZafFileSystem *FirstFileSystem(void) const;
	ZafFileSystem *LastFileSystem(void) const;
	virtual ZafClassID CurrentClassID(void);
	virtual ZafClassName CurrentClassName(void);

	// --- Attributes/Data access ---
	// get
	ZafError Error(void) const;
	const ZafIChar *CurrentLanguage(void) const;
	// set
	ZafError SetError(ZafError error);
	int PopLanguage(void);
	int PushLanguage(const ZafIChar *language);

protected:
	ZafError error;
	ZafList subSystem;

	int currentEntry;
	struct
	{
		int level;
		ZafPersistEntryType type;
		ZafClassName className;
		ZafClassID classID;
		ZafFile *file;
		ZafFileSystem *fileSystem;
		ZafIChar restorePath[ZAF_MAXPATHLEN];
	} entry[ZAF_MAXFILES];

	int currentLanguage;
	ZafIChar *language[ZAF_MAXFILES];

	DataConstructor *dataConstructor;
};

// --- inline functions ---
inline ZafError ZafDataPersistence::Error(void) const { return (error); }
inline const ZafIChar *ZafDataPersistence::CurrentLanguage(void) const { return (language[currentLanguage]); }
inline ZafFile *ZafDataPersistence::CurrentFile(void) const { return (entry[currentEntry].file); }
inline ZafFileSystem *ZafDataPersistence::CurrentFileSystem(void) const { return (entry[currentEntry].fileSystem); }
inline ZafFileSystem *ZafDataPersistence::FirstFileSystem(void) const { return ((ZafFileSystem *)subSystem.First()); }
inline ZafFileSystem *ZafDataPersistence::LastFileSystem(void) const { return ((ZafFileSystem *)subSystem.Last()); }
inline ZafError ZafDataPersistence::SetError(ZafError setError) { return (error = setError); }

// --- global variable declarations ---
extern ZAF_EXPORT ZafDataPersistence *zafDataPersistence;
#endif

// --------------------------------------------------------------------------
// ----- ZafData ------------------------------------------------------------
// --------------------------------------------------------------------------

class ZAF_EXPORT ZafData : public ZafElement, public ZafNotification
{
public:
	// --- General members ---
	virtual ~ZafData(void);

	// --- Persistent members --
#if defined(USE_ZAF_PERSISTENCE)
	ZafData(const ZafIChar *name, ZafDataPersistence &persist);
	virtual void Write(ZafDataPersistence &persist);
#endif
	virtual ZafData *Duplicate(void) = 0;

	// --- Attributes/Data access ---
	// get
	bool Destroyable(void) const;
	ZafError Error(void) const;
	virtual ZafData *GetObject(ZafNumberID numberID);
	virtual ZafData *GetObject(const ZafIChar *stringID);
	// set
	virtual void Clear(void) = 0;
	bool SetDestroyable(bool destroyable);
	ZafError SetError(ZafError error);

	// --- Element members ---
	ZafData *Next(void) const { return((ZafData *)next); }
	ZafData *Previous(void) const { return((ZafData *)previous); }

	// --- Class identification ---
	static ZafClassID classID;
	static ZafClassNameChar ZAF_FARDATA className[];
	virtual ZafClassID ClassID(void) const { return (classID); }
	virtual ZafClassName ClassName(void) const { return (className); }
	virtual bool IsA(ZafClassID compareID) const;
	virtual bool IsA(ZafClassName compareName) const;

	virtual ZafEventType Event(const ZafEventStruct &event);

	// --- Unicode support ---
#	if defined(ZAF_UNICODE)
	virtual ZafData *GetObject(const char *stringID);
#	endif

protected:
	// --- General members ---
	ZafData(void);
	ZafData(const ZafData &copy);
	int PopLevel(bool notify = true);
	int PushLevel(void);

#if defined(USE_ZAF_PERSISTENCE)
	// --- Persistent members --
	virtual ZafDataConstructor ReadFunction(void) = 0;
#endif

private:
	// --- General members ---
	ZafError error;
	int level;
	bool destroyable;
};

// --- inline functions ---
inline bool ZafData::Destroyable(void) const { return (destroyable); }
inline ZafError ZafData::Error(void) const { return (error); }
inline bool ZafData::SetDestroyable(bool tDestroyable) { destroyable = tDestroyable; return (destroyable); }

// --------------------------------------------------------------------------
// ----- ZafDataRecord ------------------------------------------------------
// --------------------------------------------------------------------------

class ZAF_EXPORT ZafDataRecord : public ZafData, public ZafList
{
public:
	// --- General members ---
	ZafDataRecord(void);
	virtual ~ZafDataRecord(void);

#if defined(USE_ZAF_PERSISTENCE)
	// --- Persistent members --
	ZafDataRecord(const ZafIChar *name, ZafDataPersistence &persist);
	static ZafElement *Read(const ZafIChar *name, ZafDataPersistence &persist);
	virtual void Write(ZafDataPersistence &persist);
#endif
	virtual ZafData *Duplicate(void);

	// --- Attributes/Data access ---
	// set
	virtual void Clear(void);

	// --- ZafData members ---
	virtual ZafData *GetObject(ZafNumberID numberID);
	virtual ZafData *GetObject(const ZafIChar *stringID);

	// --- List members ---
	virtual ZafData *Add(ZafData *object, ZafData *position = ZAF_NULLP(ZafData));
	ZafData *Current(void) const { return((ZafData *)current); }
	virtual void Destroy(void);
	ZafData *First(void) const { return((ZafData *)first); }
	ZafData *Last(void) const { return((ZafData *)last); }
	virtual ZafData *Subtract(ZafData *object);

	ZafDataRecord &operator+(ZafData *object) { Add(object); return(*this); }
	ZafDataRecord &operator-(ZafData *object) { Subtract(object); return(*this); }
	ZafData *operator()(int index) { return((ZafData *)ZafList::Get(index)); }

	// --- Class identification ---
	static ZafClassID classID;
	static ZafClassNameChar ZAF_FARDATA className[];
	virtual ZafClassID ClassID(void) const { return (classID); }
	virtual ZafClassName ClassName(void) const { return (className); }
	virtual bool IsA(ZafClassID compareID) const;
	virtual bool IsA(ZafClassName compareName) const;

	// --- Unicode support ---
#	if defined(ZAF_UNICODE)
	virtual ZafData *GetObject(const char *stringID);
#	endif

protected:
#if defined(USE_ZAF_PERSISTENCE)
	// --- Persistent members --
	virtual ZafDataConstructor ReadFunction(void) { return (ZafDataRecord::Read); }
#endif
};

// --------------------------------------------------------------------------
// ----- ZafDataManager -----------------------------------------------------
// --------------------------------------------------------------------------

class ZAF_EXPORT ZafDataManager : public ZafDataRecord
{
public:
	// --- General members ---
	ZafDataManager(void);
	virtual ~ZafDataManager(void);

	// --- Attributes/Data access ---
	// get
	virtual ZafData *AllocateData(const ZafIChar *stringID, ZafClassName className, ZafClassID classID);

	// --- List members ---
	ZafDataManager &operator+(ZafData *object) { Add(object); return(*this); }
	ZafDataManager &operator-(ZafData *object) { Subtract(object); return(*this); }

	// --- Class identification ---
	static ZafClassID classID;
	static ZafClassNameChar ZAF_FARDATA className[];
	virtual ZafClassID ClassID(void) const { return (classID); }
	virtual ZafClassName ClassName(void) const { return (className); }
	virtual bool IsA(ZafClassID compareID) const;
	virtual bool IsA(ZafClassName compareName) const;
};

// --- global variable declarations ---
extern ZAF_EXPORT ZafDataManager *zafDataManager;

#endif // Z_DATA_HPP

