#pragma once
#include "BasicTypeInterfaces.h"
#include "WorkspaceNodeWalker.h"
#include "WorkspaceKeyPairArray.h"
#include "SimpleArrayTemplate.h"
#include "WorkspaceString.h"

#define	NODE_NAME_LEN	128	//	ノード名標準バッファ
#define	NODE_GROW_SIZE	5	//	初期サイズ


//	宣言しておく
class CWorkspaceNode;

/*!
	ノード用メモリプール
*/
class IWorkspaceNodeArrayMemoryPool
{
public:
	//!	キーペア用メモリプール取得
	virtual IWorkspaceKeyPairArrayMemoryPool *GetKeyPairArrayMemoryPool()
	{
		return NULL;
	}

	//!	メモリブロック確保
	virtual void *AllocMemoryBlock(int blockSize, int count) = 0;

	//!	メモリブロック開放
	virtual void FreeMemoryBlock(void *memPtr) = 0;

	//!	最適チャンクサイズ取得
	int GetChunkSize();
};


/*!
	ノード配列クラス補助クラス
*/
class CWorkspaceNodeArrayItmeConstructor
{
public:
	//!	コンストラクタを呼ぶ
	static void ConstructItem(CWorkspaceNode *item, void *userData);

	//!	デストラクタを呼ぶ
	static void DestructItem(CWorkspaceNode *item, void *userData);
};


/*!
	ノード配列型の宣言
*/
class CWorkspaceNodeArray : public CSimpleArrayTemplate<CWorkspaceNode, CWorkspaceNode&, CWorkspaceNodeArrayItmeConstructor, NODE_GROW_SIZE>
{
public:
	//	コンストラクタ
	CWorkspaceNodeArray(IWorkspaceNodeArrayMemoryPool *memoryPool)
	{
		SetConstructorsUserData(memoryPool);
	}
};


/*!
	ワークスペースのノード保持クラス
*/
class CWorkspaceNode
{
public:
	CWorkspaceNode(const CWorkspaceNode &othe);
	CWorkspaceNode(IWorkspaceNodeArrayMemoryPool *memoryPool);
	CWorkspaceNode(IWorkspaceNodeArrayMemoryPool *memoryPool, LPCSTR name);
	~CWorkspaceNode(void);

	/*********************************************************
		初期化など
	**********************************************************/
	//!	CArrayで利用するための、コピー演算子
	void operator=(const CWorkspaceNode &other);

	//!	全データクリア
	void Clear(void);

	//!	ノード名の設定
	void SetNodeName(LPCSTR name) { m_nodeName = name; };

	//!	ノード名の取得
	LPCSTR GetNodeName() const { return(m_nodeName); }; 


	/*********************************************************
		Keyに関する処理
	**********************************************************/
	//!	データの設定
	void SetKeyData(LPCSTR key, LPCSTR data,int noCase);

	//!	データの取得
	LPCSTR GetKeyData(LPCSTR key, LPCSTR defaultData, int noCase);

	//!	データの削除
	void DeleteKey(LPCSTR key);

	//!	キー数を取得
	int GetKeyCount();

	//!	全てのキー名を文字列として取得
	int GetAllKeyPair(IStringArrayPtr keys, IStringArrayPtr datas);


	//!	キーを検索
	int FindKeyData(LPCSTR sData, int noCase = FALSE, int pathCompare = FALSE);

	//!	キーをまとめて設定
	void ClearAndSetKeys(CStringArray &keys, CStringArray &datas);

	/******************************************************
		サブノードに関する処理
	*******************************************************/
	//!	サブノードを下層も含めて検索する(無ければ追加する)
	CWorkspaceNode *GetSubNode(CWorkspaceNodeWalker &path, CWorkspaceString255 &key);

	//!	ノードを削除する
	void DeleteNode(LPCSTR name);

	//!	サブノード数を得る
	int GetSubNodeCount();

	//!	全てのサブノード名を文字列として取得
	int GetAllSubNode(IStringArrayPtr list);


	/******************************************************
		入出力に関する処理
	*******************************************************/
	//!	サブノードを名前から取得・作成する
	CWorkspaceNode *GetSubNodeByName(LPCSTR name, int errorIfExist = FALSE);

	//!	サブノードをインデックスで取得する
	CWorkspaceNode *GetSubNodeByIndex(int index);

	//!	キーをインデックスで取得する
	CWorkspaceKeyPair *GetKeyByIndex(int index);

protected:
	/******************************************************
		Keyに関する処理
	*******************************************************/
	//!	Keyの検索
	int FindKeyIndex(LPCSTR key,int noCase);

	/******************************************************
		サブノードに関する処理
	*******************************************************/
	//!	サブノードを検索する
	int FindSubNodeIndex(LPCSTR name);

	/******************************************************
		メモリプール関係の処理
	*******************************************************/
	//!	IWorkspaceKeyPairArrayMemoryPoolを取得
	IWorkspaceKeyPairArrayMemoryPool *GetPairArrayMemoryPool(IWorkspaceNodeArrayMemoryPool *basePool);

protected:
	//!	このノードの持つデータ
	CWorkspaceKeyPairArray			m_keyData;

	//!	サブノート
	CWorkspaceNodeArray				m_subNode;

	//!	このノードの名前
	CWorkspaceString<NODE_NAME_LEN>	m_nodeName;

	//!	メモリプール
	IWorkspaceNodeArrayMemoryPool	*m_memoryPool;
};

