#include "stdafx.h"
#include "UINpcTelling.h"

#include "Parser.h"
#include "Page.h"
#include "QuestDefine.h"
#include "UIManager.h"
#include "Npc_Common.h"

cUINpcTelling::cUINpcTelling()
: mDefaultTextIndex(0)
, mTarotIndex(0)
, mSpreadCount(0)
, mTarotPrice(0)
, mFuncCount(0)
{
	memset( mSpreadIndex, 0, sizeof(mSpreadIndex) );
	memset( mFunc, 0, sizeof(mFunc) );
}

cUINpcTelling::~cUINpcTelling()
{
	cQuestLinkPage::cIterator i = mQuestLinkPage.Begin();
	cQuestLinkPage::cIterator end = mQuestLinkPage.End();

	for( ; i != end; ++i )
	{
		sQuestLinkPage* link = (sQuestLinkPage*)(i->mSecond);
		SAFE_DELETE( link );
	}
	mQuestLinkPage.Clear();
}

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

	cToken token;
	cLexer* lexer = parser.GetLexer();

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

		switch( token.mType )
		{
		case eTOKEN_STORE:
			{
				mFunc[mFuncCount] = NPC_FUNC_STORE;
				if( mFuncCount < NPC_FUNC_MAX )
				{
					mFuncCount++;
				}
				else
				{
					assert(0);
				}
			}
			break;
		case eTOKEN_WAREHOUSE:
			{
				mFunc[mFuncCount] = NPC_FUNC_WAREHOUSE;
				if( mFuncCount < NPC_FUNC_MAX )
				{
					mFuncCount++;
				}
				else
				{
					assert(0);
				}
			}
			break;
		case eTOKEN_SKILLSTORE:
			{
				mFunc[mFuncCount] = NPC_FUNC_SKILLSTORE;
				if( mFuncCount < NPC_FUNC_MAX )
				{
					mFuncCount++;
				}
				else
				{
					assert(0);
				}
			}
			break;
		case eTOKEN_DISJOINT:
			{
				mFunc[mFuncCount] = NPC_FUNC_ITEMDISJOINT;
				if( mFuncCount < NPC_FUNC_MAX )
				{
					mFuncCount++;
				}
				else
				{
					assert(0);
				}
			}
			break;
		case eTOKEN_GUILD:
			{
				mFunc[mFuncCount] = NPC_FUNC_GUILD;
				if( mFuncCount < NPC_FUNC_MAX )
				{
					mFuncCount++;
				}
				else
				{
					assert(0);
				}
			}
			break;
		case eTOKEN_DEFAULT:
			{
				mDefaultTextIndex = parser.ParseInt();

				unsigned long temp = 0;
				if( LoadPageList( parser, temp ) == false )
					return false;
			}
			break;
		case eTOKEN_QUEST:
			{
				unsigned long questIndex = parser.ParseInt();
				
				sQuestLinkPage* linkPage = new sQuestLinkPage;
                
				/// 퀘스트 연결 대화 파싱
				if( LoadQuestLink( parser, linkPage ) == false )
				{
					assert( 0 && "failed to load page" );
					SAFE_DELETE( linkPage );
					return false;
				}

				/// 퀘스트 링크 맵에 담기
				if( mQuestLinkPage.Insert( questIndex, linkPage ) == false )
				{
					assert( 0 && "failed to insert quest link page" );
					SAFE_DELETE( linkPage );
					return false;
				}
			}
			break;
		case eTOKEN_TAROT:
			{
				mFunc[mFuncCount] = NPC_FUNC_TAROT;
				if( mFuncCount < NPC_FUNC_MAX )
				{
					mFuncCount++;
				}
				else
				{
					assert(0);
				}

				/// 타롯 덱 인덱스
				mTarotIndex = parser.ParseInt();

				/// 타로 요금
				mTarotPrice = parser.ParseInt();
			}
			break;
		case eTOKEN_SPREAD:
			{
				/// 보유한 스프레드 인덱스
				if( parser.ExpectTokenString( "{" ) == false )
					return false;

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

					if( token.mType == eTOKEN_INT )
					{
						mSpreadIndex[mSpreadCount] = (unsigned long)token.ToInt();
						mSpreadCount++;
					}

					if( mSpreadCount > 5 )
					{
						assert(0);
						break;
					}
				}
			}
			break;
		default:
			assert( 0 && "invalid token" );
			return false;
		}
	}
	return true;
}

bool cUINpcTelling::LoadQuestLink( cParser& parser, sQuestLinkPage* linkPage )
{
	if( parser.ExpectTokenString( "{" ) == false )
		return false;

	cToken token;
	cLexer* lexer = parser.GetLexer();
	
	unsigned long rewardIndex = 0;
	while( lexer->GetNextToken( &token ) )
	{
		if( token == "}" )
			break;

		switch( token.mType )
		{
		case eTOKEN_LCURLY:
			continue;
		case eTOKEN_NEW:
			{	
				linkPage->newIndex = (unsigned long)parser.ParseInt();

				if( LoadPageList( parser, rewardIndex ) == false )
					return false;
			}
			break;
		case eTOKEN_PLAY:
			{
				linkPage->playIndex = (unsigned long)parser.ParseInt();

				if( LoadPageList( parser, rewardIndex ) == false )
					return false;
			}
			break;
		case eTOKEN_COMPLETE:
			{
				linkPage->completeIndex = (unsigned long)parser.ParseInt();
				if( LoadPageList( parser, rewardIndex ) == false )
					return false;

				linkPage->rewardIndex = rewardIndex;
			}
			break;
		default:
			assert( 0 && "invalid token" );
			return false;
		}
	}
	return true;
}

bool cUINpcTelling::LoadPageList( cParser& parser, unsigned long& rewardIndex )
{	
	if( parser.ExpectTokenString( "{" ) == false )
		return false;

	cToken token;
	cLexer* lexer = parser.GetLexer();

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

		if( token.mType == eTOKEN_PAGE )
		{
			unsigned long pageIndex = parser.ParseInt();

			/// 새 페이지 생성
			cPage* page = new cPage;

			if( LoadPage( parser, page ) == false )
			{
				assert( 0 && "failed to load page data" );
				SAFE_DELETE( page );
				return false;
			}

			/// 보상 페이지는 complete 페이지로부터 시작한다
			if( page->mAnswerType == eEVENT_COMPLETE )
				rewardIndex = pageIndex;

			/// 페이지 삽입
			if( UIMAN->AddPage( pageIndex, page ) == false )
			{
				assert( 0 && "failed to insert page data" );
				SAFE_DELETE( page );
				return false;
			}
		}
		else
		{
			assert( 0 && "invalid token" );
			return false;
		}
	}
	return true;
}

bool cUINpcTelling::LoadPage( cParser& parser, cPage* page )
{
	if( parser.ExpectTokenString( "{" ) == false )
		return false;

	cToken token;
	cLexer* lexer = parser.GetLexer();

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

		switch( token.mType )
		{
		case eTOKEN_TEXT:
			{
				sPageText* pageText = new sPageText;
				pageText->textIndex = (unsigned int)parser.ParseInt();
				pageText->numLine = (unsigned int)parser.ParseInt();

				/// 기본대사 배열에 추가
				page->mDefaultTextArray.PushBack( pageText );
			}
			break;
		case eTOKEN_ANSWER:
			{
				/// 분기대사와 다음 페이지 넘기기는 동시에 있을수 없다
				if( page->mNextPageIndex > 0 )
				{
					assert(0);
					return false;
				}

				sPageAnswer* pageAns = new sPageAnswer;
				pageAns->textIndex = (unsigned int)parser.ParseInt();
				pageAns->numLine = (unsigned int)parser.ParseInt();
				pageAns->nextPageIndex = (unsigned int)parser.ParseInt();

				/// 분기 대사 배열에 추가
				page->mAnswerArr.PushBack( pageAns );
			}
			break;
		case eTOKEN_SOUND:
			break;
		case eTOKEN_SCENE:
			{
				page->mSceneIndex = (unsigned long)parser.ParseInt();
			}
			break;
		case eTOKEN_NEXT:
			{
				/// 분기대사와 다음 페이지 넘기기는 동시에 있을수 없다
				if( page->mAnswerArr.GetSize() > 0 )
				{
					assert(0);
					return false;
				}

				page->mNextPageIndex = (unsigned long)parser.ParseInt();

			}
			break;
		case eTOKEN_EVENTYES:
			{
				page->mAnswerType = eEVENT_YES;
			}
			break;
		case eTOKEN_EVENTREWARD:
			{
				page->mAnswerType = eEVENT_REWARD;
			}
			break;
		case eTOKEN_EVENTCOMPLETE:
			{
				page->mAnswerType = eEVENT_COMPLETE;
			}
			break;
		default:
			assert( 0 && "invalid token" );
			return false;
		}
	}
	return true;
}

/// 기본대사 랜덤으로 획득
sPageText* cUINpcTelling::GetDefaultTextRandomly()
{
	cPage* page = GetPage( mDefaultTextIndex );
	if( !page )
	{
		assert(0);
		return 0;
	}

	unsigned int i = page->mDefaultTextArray.GetSize();
	i = rand() % i;

	return (sPageText*)page->mDefaultTextArray[i];
}

unsigned long cUINpcTelling::GetDefaultScene()
{
	cPage* page = GetPage( mDefaultTextIndex );
	if( !page )
	{
		assert(0);
		return 0;
	}

	return page->GetSceneIdx();
}

/// 퀘스트 관련 페이지 정보 획득
sQuestLinkPage* cUINpcTelling::GetQuestLinkPage( unsigned long questIdx )
{
	return (sQuestLinkPage*)mQuestLinkPage.GetAt( questIdx );
}

cPage* cUINpcTelling::GetPage( unsigned long pageIdx )
{
	return UIMAN->GetPage( pageIdx );
}

////////////////////////////////////////////////
cUINpcLexer::cUINpcLexer( const char* buffer, unsigned int size )
: cLexer( buffer, size )
{
	BindKeyword( "npc_telling", eTOKEN_NPC_TELLING );

	BindKeyword( "store", eTOKEN_STORE );
	BindKeyword( "warehouse", eTOKEN_WAREHOUSE );
	BindKeyword( "skillstore", eTOKEN_SKILLSTORE );
	BindKeyword( "default", eTOKEN_DEFAULT );
	BindKeyword( "disjoint", eTOKEN_DISJOINT );
	BindKeyword( "guild", eTOKEN_GUILD );
	BindKeyword( "tarot", eTOKEN_TAROT );
	BindKeyword( "spread", eTOKEN_SPREAD );
	BindKeyword( "quest", eTOKEN_QUEST );

	BindKeyword( "text", eTOKEN_TEXT );
	BindKeyword( "page", eTOKEN_PAGE );

	BindKeyword( "new", eTOKEN_NEW );
	BindKeyword( "play", eTOKEN_PLAY );
	BindKeyword( "complete", eTOKEN_COMPLETE );

	BindKeyword( "answer", eTOKEN_ANSWER );
	BindKeyword( "sound", eTOKEN_SOUND );
	BindKeyword( "scene", eTOKEN_SCENE );

	BindKeyword( "next", eTOKEN_NEXT );
	BindKeyword( "EVENT_YES", eTOKEN_EVENTYES );
	BindKeyword( "EVENT_REWARD", eTOKEN_EVENTREWARD );
	BindKeyword( "EVENT_COMPLETE", eTOKEN_EVENTCOMPLETE );

	BindKeyword( "event_yes", eTOKEN_EVENTYES );
	BindKeyword( "event_reward", eTOKEN_EVENTREWARD );
	BindKeyword( "event_complete", eTOKEN_EVENTCOMPLETE );
}

