#include "StdAfx.h"
#include "UIFuncText.h"

#include "UINode.h"
#include "Parser.h"

cUIFuncText::cUIFuncText()
{
}

cUIFuncText::~cUIFuncText()
{
	Clear();
}

void cUIFuncText::Clear()
{
	cNodeMap::cIterator i = mNodeMap.Begin();
	cNodeMap::cIterator iend = mNodeMap.End();

	for( ; i != iend; ++i )
	{
		cUIFuncTextNode* n = (cUIFuncTextNode*)i->mSecond;
		delete n;
	}

	mNodeMap.Clear();
}

bool cUIFuncText::Load( const cString& pathName )
{
	Clear();

	/// 파일 열기
	cFileLoader loader;
	if( loader.Open( pathName, true ) == false )
	{
		return false;
	}

	/// 렉서에 밥주고 파싱
	cToken token;
	cUIFuncTextLexer lexer( loader.GetBufferPtr(), loader.GetSize() );
	cParser parser( &lexer, pathName );
	cString text;
	unsigned int id = 0;

	while( lexer.IsEnd() == false )
	{
		lexer.GetNextToken( &token );

		switch( token.mType )
		{
		case eTOKEN_ERROR:
			return false;

		case eTOKEN_NULL:
			continue;

		case eTOKEN_INT:
			id = token.ToInt();
			break;

		case eTOKEN_STR:
			PushStringNode( id, token );
			break;

		case eTOKEN_TEXT_BLACK:
			PushColorNode( id, eCOLOR_BLACK );
			break;

		case eTOKEN_TEXT_WHITE:
			PushColorNode( id, eCOLOR_DEFAULT );
			break;

		case eTOKEN_TEXT_GRAY:
			PushColorNode( id, eCOLOR_GRAY );
			break;

		case eTOKEN_TEXT_RED:
			PushColorNode( id, eCOLOR_RED );
			break;

		case eTOKEN_TEXT_GREEN:
			PushColorNode( id, eCOLOR_GREEN );
			break;

		case eTOKEN_TEXT_BLUE:
			PushColorNode( id, eCOLOR_SKYBLUE );
			break;

		case eTOKEN_TEXT_YELLOW:
			PushColorNode( id, eCOLOR_YELLOW );
			break;

		case eTOKEN_TEXT_VARNAME:
			PushVarNameNode( id );
			break;

		case eTOKEN_TEXT_NEWLINE:
			PushNewLineNode( id );
			break;

		default:
			{
				char buf[256] = {0,};
				::sprintf( buf, "error %s file", pathName.Cstr() );
				NiMessageBox( buf, "error");
			}
			return false;
		}
	}
	return true;
}

cUIFuncTextNode* cUIFuncText::NewNode( unsigned int id )
{
	cUIFuncTextNode* n = 0;
	cNodeMap::cIterator i = mNodeMap.Find( id );

	if( i == mNodeMap.End() )
	{
		n = new cUIFuncTextNode;
		mNodeMap.Insert( id, n );
	}
	else
	{
		n = ((cUIFuncTextNode*)i->mSecond)->Back()->mpNext = new cUIFuncTextNode;
	}
	return n;
}

void cUIFuncText::PushStringNode( unsigned int id, const cString& str )
{
	if( str.IsEmpty() )
		return;

	cUIFuncTextNode* n = NewNode( id );

	n->mType = eTEXTNODE_STRING;

	wchar_t buffer[256] = {0,};
	int len = ConvertToUnicode( str.Cstr(), buffer, 256 );
	assert( len > 0 );

	wchar_t* dest = n->mpString = new wchar_t[len+1];
	::_tcsncpy( dest, buffer, len );
	dest[len] = 0;

	//n->mpString = new wchar_t[len+1];
	//::_tcsncpy( n->mpString, buffer, len );
	//n->mpString[len] = 0;
}

void cUIFuncText::PushColorNode( unsigned int id, unsigned long color )
{
	cUIFuncTextNode* n = NewNode( id );

	n->mType = eTEXTNODE_COLOR;
	n->mColor = color;
}

void cUIFuncText::PushVarNameNode( unsigned int id )
{
	cUIFuncTextNode* n = NewNode( id );

	n->mType = eTEXTNODE_VARNAME;
	n->mColor = 0;
}

void cUIFuncText::PushNewLineNode( unsigned int id )
{
	cUIFuncTextNode* n = NewNode( id );
	n->mType = eTEXTNODE_NEWLINE;
	n->mColor = 0;
}

const cUIFuncTextNode* cUIFuncText::GetNode( unsigned int id ) const
{
	cNodeMap::cConstIterator i = mNodeMap.Find( id );

	if( i == mNodeMap.End() )
	{
		assert( 0 && "failed to find npc text node" );
		return 0;
	}
	else
		return (cUIFuncTextNode*)i->mSecond;
}

cUIFuncTextLexer::cUIFuncTextLexer( const char* buffer, unsigned int size )
: cLexer( buffer, size )
{
	BindKeyword( "black", eTOKEN_TEXT_BLACK );
	BindKeyword( "white", eTOKEN_TEXT_WHITE );
	BindKeyword( "gray", eTOKEN_TEXT_GRAY );
	BindKeyword( "red", eTOKEN_TEXT_RED );
	BindKeyword( "green", eTOKEN_TEXT_GREEN );
	BindKeyword( "blue", eTOKEN_TEXT_BLUE );
	BindKeyword( "yellow", eTOKEN_TEXT_YELLOW );
	BindKeyword( "name", eTOKEN_TEXT_VARNAME );
	BindKeyword( "enter", eTOKEN_TEXT_NEWLINE );
}
