#include "stdafx.h"
#include "ItemManager.h"

#include "Parser.h"
#include "Lexer.h"

/// Npc 상점 토큰 타입
enum
{
	/// Npc 상점
	eTOKEN_NPCSTORE = 100,

	/// 기능
	eTOKEN_TAB
};

/// Npc 상점 어휘 분석기
class cItemNpcStoreLexer : public cLexer
{
public:
	cItemNpcStoreLexer( const char* buffer, unsigned int size );
};

cItemNpcStoreLexer::cItemNpcStoreLexer( const char* buffer, unsigned int size )
: cLexer( buffer, size )
{
	BindKeyword( "npc_store", eTOKEN_NPCSTORE );
	BindKeyword( "tab", eTOKEN_TAB );
}

void cItemNpcStore::Clear()
{
	/// 데이터 삭제
	for( unsigned int i = 0; i < mDataCount; ++i )
		mItemData[i].mItemArr.Clear();
}

bool cItemNpcStore::Load( cParser& parser )
{
	if( parser.ExpectTokenString( "{" ) == false )
		return false;

	cToken token;
	cLexer* lexer = parser.GetLexer();
	if( !lexer )
	{
		assert(0);
		return false;
	}

	while( lexer->GetNextToken( &token ) )
	{
		if( token == "}" )
			break;

		switch( token.mType )
		{
		case eTOKEN_TAB:
			{
				/// 탭 인덱스
				unsigned long textIdx = parser.ParseInt();

				if( mDataCount > NPCSTORE_TAB_COUNT )
				{
					assert( 0 && "tab index out of range" );
					return false;
				}

				/// 데이터 로딩
				mItemData[mDataCount].mTextIndex = textIdx;
				if( LoadTab( parser ) == false )
				{
					assert( 0 );
					return false;
				}

				mDataCount++;
			}
			break;
		default:
			assert( 0 && "invalid token" );
			return false;
		}
	}
	return true;
}

/// 서버의 로딩부도 동시에 바꿔야함!!!!!!!!!!!! 
bool cItemNpcStore::LoadTab( cParser& parser )
{
	if( parser.ExpectTokenString( "{" ) == false )
		return false;

	cToken token;
	cLexer* lexer = parser.GetLexer();
	if( !lexer )
	{
		assert(0);
		return false;
	}

	while( lexer->GetNextToken( &token ) )
	{
		if( token == "}" )
			break;

		switch( token.mType )
		{
		case eTOKEN_INT:
			{
				unsigned long itemIndex = (unsigned long)token.ToInt();
				mItemData[mDataCount].mItemArr.PushBack( itemIndex );
			}
			break;
		default:
			assert( 0 && "invalid token" );
			return false;
		}
	}
	return true;
}

bool cItemManager::LoadNpcStore( const cString& pathName )
{
	/// 파일 열기
	cFileLoader loader;

	if( loader.Open( pathName, true ) == false )
	{
		assert( 0 && "failed to load npc store" );
		return false;
	}

	/// 렉서에 밥주고 파싱
	cToken token;
	cItemNpcStoreLexer lexer( loader.GetBufferPtr(), loader.GetSize() );
	cParser parser( &lexer, pathName );

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

		switch( token.mType )
		{
		case eTOKEN_ERROR:
			return false;
		case eTOKEN_NULL:
			continue;
		case eTOKEN_NPCSTORE:
			{
				/// Npc 인덱스
				unsigned int i = parser.ParseInt();

				/// Npc 상점 생성
				cItemNpcStore* p = new cItemNpcStore;

				/// 로딩
				if( p->Load( parser ) == false )
				{
					delete p;
					return false;
				}

				/// Npc 상점 맵에 추가
				if( mNpcStoreMap.Insert( i, p ) == false )
				{
					assert( 0 && "failed to insert npc store, maybe already exist" );
					return false;
				}
			}
			break;
		default:
			assert( 0 && "invalid token" );
			return false;
		}
	}
	return true;
}

cItemNpcStore* cItemManager::GetItemNpcStore( unsigned int npcIndex )
{
	cNpcStoreMap::cConstIterator i = mNpcStoreMap.Find( npcIndex );

	if( i == mNpcStoreMap.End() )
		return 0;
	else
		return (cItemNpcStore*)i->mSecond;
}
