/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 1, or (at your option)
** any later version.

** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.

** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
 * Author : Alexandre Parenteau <aubonbeurre@hotmail.com> --- December 1997
 */

/*
 * Persistent.h --- utilities to store persitent values
 */

#ifndef PERSISTENT_H
#define PERSISTENT_H

#include <string.h>
#include <vector>
#include "uobject.h"

#ifdef macintosh
#	include <Files.h>
#endif /* macintosh */

typedef enum
{
	kNoClass = 0x00,
	kAddSettings = 0x01
} kClassPersistent;

// virtual class to access the persistent data to load/save
class CPersistent : public UObject
{
	UDECLARE_DYNAMIC(CPersistent)
public:
	CPersistent(const char *uniqueName, kClassPersistent pclass);
	virtual ~CPersistent();

	virtual unsigned int SizeOf(void) const = 0L;
	virtual const void *GetData(void) const = 0L;
	virtual void SetData(const void *ptr, unsigned int size) = 0L;
		// virtual access
	
	static void SaveAll(void);
	static bool LoadAll(void);
		// save/load the registred values

	static bool SaveAllSettings(const char *settingFileName, const char *forPath);
		// save all the persistent values with the class 'kAddSettings'

	struct CPersistentEntry
	{
		const char *fUniqueName;
		CPersistent *fValue;
		kClassPersistent fClass;
	};

	static CPersistentEntry * Find(const char *uniqueName);

	// handle modification flag (see if we really need to save it)
	inline void ResetTimeStamp() { fTimeStamp = 0; }
	inline long GetTimeStamp() const { return fTimeStamp; }
	inline void TouchTimeStamp() { fTimeStamp++; }

	static bool NeedSave(bool onlySettings = false);

private:
	static void Register(CPersistent *value, const char *uniqueName,
		kClassPersistent pclass);
	static void UnRegister(CPersistent *value);
		// register/unregister a value to store/load
	
protected:
	long fTimeStamp;
	static std::vector<CPersistentEntry> *fAllEntries;
};

#define PERSISTENT_CAST(T) \
	inline operator const T &() const {return fValue;} \
	inline const T * operator ->() const {return &fValue;} \
	inline T & operator=(const T & val) { TouchTimeStamp(); return fValue = val;} \
	inline bool operator==(const T & val) const {return fValue == val;}

// this is OK for most of the persistant values

template <class T>
class CPersistentT : public CPersistent
{
public:
	CPersistentT(const char *uniqueName, T defValue, kClassPersistent pclass) : CPersistent(uniqueName, pclass)
	{
		fValue = fDefValue = defValue;
	}
	virtual ~CPersistentT()
	{
	}

	PERSISTENT_CAST(T)

	virtual unsigned int SizeOf(void) const {return sizeof(T);}
	virtual const void *GetData(void) const {return &fValue;}
	virtual void SetData(const void *ptr, unsigned int size)
	{
		if(size == sizeof(T))
			memcpy(&fValue, ptr, size);
	}
	
protected:
	T fDefValue, fValue;
};

class CPersistentBool : public CPersistentT<bool>
{
	UDECLARE_DYNAMIC(CPersistentBool)
public:
	CPersistentBool(const char *uniqueName, bool defValue,
		kClassPersistent pclass = kNoClass) :
	  CPersistentT<bool>(uniqueName, defValue, pclass)
	{
	}
	virtual ~CPersistentBool()
	{
	}

	PERSISTENT_CAST(bool)
};

class CPersistentInt : public CPersistentT<int>
{
	UDECLARE_DYNAMIC(CPersistentInt)
public:
	CPersistentInt(const char *uniqueName, int defValue,
		kClassPersistent pclass = kNoClass) :
			CPersistentT<int>(uniqueName, defValue, pclass)
	{
	}
	virtual ~CPersistentInt()
	{
	}

	PERSISTENT_CAST(int)
};

#ifdef macintosh
	OSErr MacGetSpecialFolder(FSSpec & theFolder, Str255 & thePath, OSType inType, const char* inDesc);
	OSErr MacGetTempFolder(FSSpec & theFolder, Str255 & thePath);
	OSErr MacGetPrefsFolder(FSSpec & theFolder, Str255 & thePath);
#endif /* macintosh */

#ifdef WIN32
#	define PROFILE_NAME "CVS settings"
#endif /* WIN32 */

// Persistent settings API
void LoadPersistentSettings(const char *path);
bool HasPersistentSettings(const char *path);
void AskCreatePersistentSettings(const char *path);
void SavePersistentSettings(const char *path);

#endif /* PERSISTENT_H */
