#include"CXMLReader.h"
#include"../Debug/CAssert.h"
#include"../Debug/CTrace.h"
#include"../CString.h"


namespace Maid
{
	/*!
	 	@class	CXMLReader CXMLReader.h
	 	@brief	XMLを順番に読んでいくクラス
	 */

void CXMLReader::Load( const mstring& FileName )
{
	m_Docment.Load(FileName);
}

void CXMLReader::LoadText( const MySTL::vector<unt08>& TextImage )
{
	mstring Text;
	
	MySTL::vector<unt08> dat = TextImage;
	dat.push_back('\0');

	Text = CString::ConvertSJIStoMAID((char*)&dat[0]);

	m_Docment.LoadText(Text);
}

void CXMLReader::NextNode()
{
	if( m_ParentStack.empty() ) { return ; }

	NODESTACK& s = m_ParentStack.top();

	if( s.ChildPos < s.ParentNode.GetChildLength() )
	{
		++s.ChildPos;
	}
}

bool CXMLReader::IsEndNode()
{
	if( m_ParentStack.empty() ) { return true; }

	NODESTACK& s = m_ParentStack.top();

	return s.ChildPos == s.ParentNode.GetChildLength();
}

bool CXMLReader::IsTopNode()
{
	return m_ParentStack.empty();
}

void CXMLReader::AscendNode()
{
	NODETYPE t = GetNodeType();

	MAID_ASSERT( t!=NODETYPE_TAG&&t!=NODETYPE_EMPTY, "子持ちではありません" );

	CXMLNode& node = GetCurrentNode();

//	MAID_TRACE( MAIDTEXT("AscendNode()") << node.GetName() );
	m_ParentStack.push( NODESTACK(node) );
}

void CXMLReader::DescendNode()
{
/*
	if( !m_ParentStack.empty() )
	{
		CXMLNode& node = m_ParentStack.top().ParentNode;
		MAID_TRACE( MAIDTEXT("DescendNode()") << node.GetName() );
	}else
	{
		MAID_TRACE( MAIDTEXT("DescendNode()")  );

	}
*/
	m_ParentStack.pop();
}

CXMLReader::NODETYPE CXMLReader::GetNodeType()const
{
	CXMLNode& node = GetCurrentNode();

	if( node.GetType()!=CXMLNode::TYPE_ELEMENT ) { return NODETYPE_EMPTY; }


	int text_count=0;
	int element_count=0;
	int comment_count=0;
	for( int i=0; i<node.GetChildLength(); ++i )
	{
		switch( node.GetChildNode(i).GetType() )
		{
		case CXMLNode::TYPE_TEXT:	 { ++text_count;	}break;
		case CXMLNode::TYPE_ELEMENT: { ++element_count; }break;
		case CXMLNode::TYPE_COMMENT: { ++comment_count; }break;

		case CXMLNode::TYPE_EMPTY:
		default:					{ MAID_ASSERT( true, "ここはありえない" ); }break;
		}
	}

	if( element_count==0 )
	{
		if( text_count==1 ) { return NODETYPE_ELEMENT; }
		return NODETYPE_EMPTY;
	}else
	{
		return NODETYPE_TAG;
	}

	//	そうでないならデータ
	return NODETYPE_ELEMENT;

}

CXMLNode& CXMLReader::GetCurrentNode()const
{
	if( m_ParentStack.empty() )
	{
		return const_cast<CXMLReader*>(this)->m_Docment.GetRoot();
	}

	const NODESTACK& s = m_ParentStack.top();

	return s.ParentNode.GetChildNode(s.ChildPos);
}

mstring CXMLReader::GetNodeName()const
{
	CXMLNode& node = GetCurrentNode();

	return CString::ToLower(node.GetName());
}


mstring CXMLReader::GetString()const
{
	//	テキストとして読み込む場合は空データを認める
	const NODETYPE type = GetNodeType();

	MAID_ASSERT( type!=NODETYPE_ELEMENT && type!=NODETYPE_EMPTY, "データではありません" );

	if( type==NODETYPE_EMPTY ) { return mstring(); }

	CXMLNode& n = GetTextNode( GetCurrentNode() );

	return n.GetText().GetStr();
}

int CXMLReader::GetInteger()const
{
	MAID_ASSERT( GetNodeType()!=NODETYPE_ELEMENT, "データではありません" );

	CXMLNode& n = GetTextNode( GetCurrentNode() );

	return n.GetText().GetInt();
}

float CXMLReader::GetFloat()const
{
	MAID_ASSERT( GetNodeType()!=NODETYPE_ELEMENT, "データではありません" );

	CXMLNode& n = GetTextNode( GetCurrentNode() );

	return n.GetText().GetFloat();
}

CXMLText CXMLReader::GetAttribute( const mstring& Name )const
{
	CXMLNode& n = GetCurrentNode();

	return n.GetAttribute( Name );
}


CXMLNode& CXMLReader::GetTextNode( CXMLNode& parent )const
{
	for( int i=0; i<parent.GetChildLength(); ++i )
	{
		CXMLNode& n = parent.GetChildNode(i);
		if( n.GetType()==CXMLNode::TYPE_TEXT )
		{
			return n;
		}
	}

	MAID_ASSERT( true, "テキストノードが見つかりませんでした" );

	return parent;	//	←これコンパイラ対策なので、これ自体に意味はありません
}

}