/*
** 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 persistent values
 */

#ifndef PERSISTENT_H
#define PERSISTENT_H

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

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

#if TARGET_OS_MAC
#	define kCVS_prefID 'cprf'
#	define kCVS_prefName "\pMacCvs Prefs"
#endif

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

/// Casting macro, good for most persistant values
#define PERSISTENT_CAST(T) \
	inline operator const T&() const {return fValue;} \
	inline T& operator=(const T& val) { TouchTimeStamp(); return fValue = val;} \
	inline bool operator==(const T& val) const {return fValue == val;}
	/* inline const T * operator ->() const {return &fValue;} */ \

/// Persistent classes enum
typedef enum
{
	kNoClass = 0x00,	/*!< No class */
	kAddSettings = 0x01	/*!< Add to the saved settings */
} kClassPersistent;

class UStr;

// Persistent settings API
void LoadPersistentSettings(const char* path, bool quiet = false);
bool HasPersistentSettings(const char* path);
void AskCreatePersistentSettings(const char* path);
void SavePersistentSettings(const char* path);
bool FormatDefaultSettingsLoc(UStr& path);

/// Abstract 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(const char* only = 0L);
		// save/load the registred values
		// 'only' can be used to force go load only this persistent value
		// form the disk

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

/// Template class for 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;
};

/// <b>bool</b> type persistant specialization
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)
};

/// <b>int</b> type persistant specialization
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)
};

#endif /* PERSISTENT_H */
