/*-----------------------------------------------------------------------------
[名称]	CategoryNode.cpp
[概要]	カテゴリノードの実装
[備考]	カテゴリツリーのノード。
[履歴]	2003-03-14	NC		新規作成(moralog)
-----------------------------------------------------------------------------*/


//-----------------------------------------------------------------------------
// インクルード・不完全定義
//-----------------------------------------------------------------------------
#include "stdafx.h"
#include "hebope.h"
#include "CategoryNode.h"
#include "../Common/Common.h"
#include "ExeCommon.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


/*-----------------------------------------------------------------------------
[名称]	コンストラクタ
[機能]	インスタンスの生成。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
CCategoryNode::CCategoryNode()
	: m_pParent( NULL )
{

}


/*-----------------------------------------------------------------------------
[名称]	デストラクタ
[機能]	インスタンスの破棄。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
CCategoryNode::~CCategoryNode()
{
	RemoveAllNode();
	RemoveAllIndex();
}


/*-----------------------------------------------------------------------------
[名称]	下位ノードの破棄
[機能]	動的に確保した下位ノードの解放。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CCategoryNode::RemoveAllNode()
{
	POSITION	pos = m_listpNodez.GetHeadPosition();
	while( pos != NULL )
	{
		delete ( m_listpNodez.GetNext(pos) );
	}
	m_listpNodez.RemoveAll();
}


/*-----------------------------------------------------------------------------
[名称]	ツリービューのノードに反映
[機能]	ツリービューへ反映する。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void	CCategoryNode::Reflect(
	CTreeCtrl*	pTree,
	HTREEITEM	RootNode
)
{
	// 自分のカテゴリを作成
	HTREEITEM	OwnNode = pTree->InsertItem( GetNodeName(), 0, 1, RootNode );
	pTree->SetItemData( OwnNode, (DWORD)this );

	// 下位ノードを追加
	POSITION	pos = m_listpNodez.GetHeadPosition();
	while( pos != NULL )
	{
		m_listpNodez.GetNext(pos)->Reflect( pTree, OwnNode );
	}
}

/*-----------------------------------------------------------------------------
[名称]	ノード名称の設定
[機能]	ノードの名称を変更する
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void	CCategoryNode::SetNodeName(
	CString strNodeName				// ノード新名称 [-] (-) :-
)
{
	m_strNodeName = strNodeName;

	// ドキュメントに変更あり！
	::NotifyModified();
}

/*-----------------------------------------------------------------------------
[名称]	下位ノードの追加
[機能]	
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
CCategoryNode* CCategoryNode::AddNode(
	CString&	strNodeName,
	BOOL		bForceCreate			// 必ず作る :TRUE
)
{
	// 同じ名称のノードがあればつくらない
	if ( !bForceCreate )
	{
		POSITION	pos = m_listpNodez.GetHeadPosition();
		while( pos != NULL )
		{
			CCategoryNode* pNode = m_listpNodez.GetAt( pos );
			if( pNode->GetNodeName() == strNodeName )
			{
				return( pNode );
			}
			m_listpNodez.GetNext( pos );
		}
	}

	// 新規ノード作成
	CCategoryNode* pNewNode = new CCategoryNode;
	m_listpNodez.AddTail( pNewNode );
	pNewNode->m_pParent = this;
	pNewNode->SetNodeName( strNodeName );

	// ドキュメントに変更あり！
	::NotifyModified();

	return( pNewNode );
}



/*-----------------------------------------------------------------------------
[名称]	下位ノードの削除
[機能]	
[戻値]	BOOL	処理結果[-] (TRUE:成功、FALSE:失敗)
[備考]	なし
-----------------------------------------------------------------------------*/
BOOL CCategoryNode::DeleteNode(
	CCategoryNode* pDeleteNode
)
{
	POSITION	pos = m_listpNodez.GetHeadPosition();
	while( pos != NULL )
	{
		CCategoryNode* pNode = m_listpNodez.GetAt( pos );
		if( pNode == pDeleteNode )
		{
			delete pDeleteNode;
			m_listpNodez.RemoveAt( pos );

			// ドキュメントに変更あり！
			::NotifyModified();

			return( TRUE );
		}
		m_listpNodez.GetNext( pos );
	}
	return( FALSE );
}

/*-----------------------------------------------------------------------------
[名称]	AAインデクスの取得
[機能]	
[戻値]	long AAのインデクス [-] (-1:みつからない。0〜:CAAHanger内インデクス)
[備考]	なし
-----------------------------------------------------------------------------*/
long CCategoryNode::GetIndex( long idxIndex )
{
	POSITION	pos = m_listIndexz.GetHeadPosition();
	while( pos != NULL )
	{
		if ( idxIndex == 0 )
		{
			return( m_listIndexz.GetAt(pos) );
		}
		m_listIndexz.GetNext(pos);
		idxIndex--;
	}
	return( -1 );
}



/*-----------------------------------------------------------------------------
[名称]	ファイル出力
[機能]	
[戻値]	BOOL	処理結果 [-] (:TRUE:成功、FALSE:失敗)
[備考]	なし
-----------------------------------------------------------------------------*/
BOOL CCategoryNode::Write(CArchive& ar)
{
	// ノード名称
	ar.WriteString( ::QuoteString( m_strNodeName ) );
	ar.WriteString( "\n" );

	// インデクス個数
	ar.WriteString( ::LongToString( m_listIndexz.GetCount() ) );
	ar.WriteString( "\n" );

	// インデクス群
	POSITION	posIndex = m_listIndexz.GetHeadPosition();
	while( posIndex )
	{
		ar.WriteString( ::LongToString( m_listIndexz.GetNext( posIndex ) ) );
		ar.WriteString( "\n" );
	}

	// 下位ノード個数
	ar.WriteString( ::LongToString( m_listpNodez.GetCount() ) );
	ar.WriteString( "\n" );

	// 下位ノード群
	POSITION	posNode = m_listpNodez.GetHeadPosition();
	while( posNode )
	{
		m_listpNodez.GetNext( posNode )->Write( ar );
	}

	return( TRUE );
}


/*-----------------------------------------------------------------------------
[名称]	ファイル入力
[機能]	
[戻値]	BOOL	処理結果 [-] (:TRUE:成功、FALSE:失敗)
[備考]	なし
-----------------------------------------------------------------------------*/
BOOL CCategoryNode::Read(CArchive& ar)
{
	RemoveAllNode();
	RemoveAllIndex();

	CString		strLine;

	// ノード名称
	ar.ReadString( strLine );
	m_strNodeName = ::DeQuoteString( strLine );

	// インデクス群
	long	nIndex;
	ar.ReadString( strLine );
	nIndex = ::StringToLong( strLine );
	while( nIndex > 0 )
	{
		ar.ReadString( strLine );
		m_listIndexz.AddTail( ::StringToLong( strLine ) );
		nIndex--;
	}

	// 下位ノード群
	long	nNode;
	ar.ReadString( strLine );
	nNode = ::StringToLong( strLine );
	while( nNode > 0 )
	{
		CCategoryNode*	ptmp = new CCategoryNode;
		ptmp->Read( ar );
		ptmp->m_pParent = this;
		m_listpNodez.AddTail( ptmp );
		nNode--;
	}

	return( TRUE );
}


/*-----------------------------------------------------------------------------
[名称]	下位ノードの複製追加
[機能]	
[戻値]	BOOL	処理結果 [-] (:TRUE:成功、FALSE:失敗)
[備考]	インデクス情報だけをコピーし、下位ノードはコピーしない!
-----------------------------------------------------------------------------*/
CCategoryNode* CCategoryNode::AddNode(
	CCategoryNode& Src,			// I  :複製元ノード [-] (-) :-
	CCategoryNode* pAfter		// I  :コピー先兄ノード [-] (-) :-
)
{
	CCategoryNode* pNewNode = AddNode( Src.GetNodeName() );

	pNewNode->m_listIndexz.RemoveAll();
	pNewNode->m_listIndexz.AddTail( &Src.m_listIndexz );
/*
	POSITION pos = Src.m_listpNodez.GetHeadPosition();
	while( pos != NULL )
	{
		pNewNode->AddNode(
			*(Src.m_listpNodez.GetNext( pos )),
			NULL
		);
	}
*/
	// ドキュメントに変更あり！
	::NotifyModified();

	return( pNewNode );
}


/*-----------------------------------------------------------------------------
[名称]	AAインデクスの削除
[機能]	
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CCategoryNode::DeleteIndex(
	long lIndex				// リスト内要素番号 [0〜]
)
{
	POSITION	pos = m_listIndexz.GetHeadPosition();
	while( pos != NULL )
	{
		if( lIndex == 0 )
		{
			m_listIndexz.RemoveAt(pos);

			// ドキュメントに変更あり！
			::NotifyModified();

			return;
		}
		lIndex--;
		m_listIndexz.GetNext(pos);
	}
}


// 下位ノードの取得
CCategoryNode* CCategoryNode::GetNode(
	long idxNode
)
{
	POSITION	pos = m_listpNodez.GetHeadPosition();
	while( pos != NULL )
	{
		if ( idxNode == 0 )
		{
			return( m_listpNodez.GetAt( pos ) );
		}
		idxNode--;
		m_listpNodez.GetNext(pos);
	}
	return( NULL );
}


// AAインデクスの設定
BOOL CCategoryNode::SetIndex(
	long idxItem,
	long idxAA
)
{
	POSITION	pos = m_listIndexz.GetHeadPosition();
	while( pos != NULL )
	{
		if ( idxItem == 0 )
		{
			m_listIndexz.SetAt( pos, idxAA );

			// ドキュメントに変更あり！
			::NotifyModified();

			return( TRUE );
		}
		idxItem--;
		m_listIndexz.GetNext(pos);
	}
	return( FALSE );
}



// 以下の階層のインデクスを全て列挙する
long	CCategoryNode::GetIndexz( CList<long, long>* plistlIndexz )
{
	// この階層を列挙
	plistlIndexz->AddTail( &m_listIndexz );

	// 階層下を列挙
	POSITION	pos = m_listpNodez.GetHeadPosition();
	while( pos != NULL )
	{
		m_listpNodez.GetAt( pos )->GetIndexz( plistlIndexz );
		m_listpNodez.GetNext(pos);
	}
	return ( plistlIndexz->GetCount() );
}

// インデクスの振りなおし
BOOL CCategoryNode::Renumbering( CList<long, long>& listlIndexz )
{
	// この階層
	{
		POSITION	posMy = m_listIndexz.GetHeadPosition();
		while( posMy != NULL )
		{
			long	iOldIndex = m_listIndexz.GetAt( posMy );

			long	idxNewIndex = 0;
			POSITION	posTrans = listlIndexz.GetHeadPosition();
			while( posTrans != NULL )
			{
				if ( listlIndexz.GetAt( posTrans ) == iOldIndex )
				{
					m_listIndexz.SetAt( posMy, idxNewIndex );
					break;
				}
				listlIndexz.GetNext( posTrans );
				idxNewIndex++;
			}
			m_listIndexz.GetNext( posMy );
		}
	}

	// 階層下を列挙
	POSITION	pos = m_listpNodez.GetHeadPosition();
	while( pos != NULL )
	{
		m_listpNodez.GetAt( pos )->Renumbering( listlIndexz );
		m_listpNodez.GetNext( pos );
	}

	// ドキュメントに変更あり！
	::NotifyModified();

	return ( TRUE );
}
