#ifndef __IMETADATARECORDER_H__
#define __IMETADATARECORDER_H__

#pragma once

struct IMetadata
{
	static IMetadata* CreateInstance();
	void Delete();

	virtual void SetTag(uint32 tag) = 0;
	virtual bool SetValue(uint32 type, const uint8* data, uint8 size) = 0;
	virtual bool AddField(const IMetadata* metadata) = 0;
	virtual bool AddField(uint32 tag, uint32 type, const uint8* data, uint8 size) = 0;

	virtual uint32 GetTag() const = 0;
	virtual size_t GetNumFields() const = 0; // 0 means this is a basic typed value
	virtual const IMetadata* GetFieldByIndex(size_t i) const = 0;
	virtual uint32 GetValueType() const = 0;
	virtual uint8 GetValueSize() const = 0;
	virtual bool GetValue(uint8* data /*[out]*/, uint8* size /*[in|out]*/) const = 0;

	virtual IMetadata* Clone() const = 0;

	virtual void Reset() = 0;

protected:
	virtual ~IMetadata() {}
};

// this interface should be implemented by user of IMetadataRecorder
struct IMetadataListener
{
	virtual void OnData(const IMetadata* metadata) = 0;
};

// records toplevel metadata - everything being recorded is added to the toplevel in a sequential manner
struct IMetadataRecorder
{
	static IMetadataRecorder* CreateInstance();
	void Delete();

	virtual bool InitSave(const char* filename) = 0;
	virtual bool InitLoad(const char* filename) = 0;

	virtual void RecordIt(const IMetadata* metadata) = 0;
	virtual void Flush() = 0;

	virtual bool Playback(IMetadataListener* pListener) = 0;

	virtual void Reset() = 0;

protected:
	virtual ~IMetadataRecorder() {}
};

template<typename I>
class CSimpleAutoPtr
{
public:
	CSimpleAutoPtr() { m_pI = I::CreateInstance(); }
	~CSimpleAutoPtr() { m_pI->Delete(); }
	I* operator->() const { return m_pI; }
	const I* get() const { return m_pI; }
private:
	CSimpleAutoPtr(const CSimpleAutoPtr& rhs);
	CSimpleAutoPtr& operator=(const CSimpleAutoPtr& rhs);
	I* m_pI;
};

typedef CSimpleAutoPtr<IMetadata> IMetadataPtr;
typedef CSimpleAutoPtr<IMetadataRecorder> IMetadataRecorderPtr;

#endif

