//************************************
// Method:    ShowWinline
// FullName:  BSSlotsContainer::ShowWinline
// Access:    protected 
// Returns:   bool
// Qualifier: show winline
// Parameter: const int id   :  winlinID
//************************************
bool BSSlotsContainer::SetupWinline(const int winlineID, const int timeToShowPerWinline)
{
	if(m_pTicketGenerator == NULL)
		return false;
	
	//show winline slot animations;
	if(!m_winlineReelSlotsDict.KeyExists(winlineID))
	{
		GTLogManager::SLogFormatWarning("Warning! Can not find  winline%d!", winlineID);
		return false;
	}
	
	GTArray<GTVector2>*  pWinSlotsInReel = NULL;
	m_winlineReelSlotsDict.GetValueByKey(winlineID, pWinSlotsInReel);
	if(pWinSlotsInReel != NULL)
	{
		for(int i=0; i < pWinSlotsInReel->Length(); i++)
		{
			GTVector2 value = (*pWinSlotsInReel)[i];
			int reelID = value.x;
			int slotPos = value.y; 
			m_reelColumns[reelID]->ShowWinline(winlineID, slotPos, timeToShowPerWinline);

			//GTLogManager::SLogFormatComment("-----  show winline %d    ------- reel %d  : status = %d --> slot[%d] win!!!", 
			//								it->first, reelID, m_reelColumns[reelID]->GetStatus(), slotPos);
		}
		return true;
	}

	return false;
}
//************************************
// Method:    CreateTicket
// FullName:  BSSlotsContainer::BuildTicket
// Access:    public 
// Returns:   void
// Qualifier: based on real slot symbols to build fake tickets to all reels; Fake reels(top & bottom invisible)
// Parameter: GTArray<int> slotSymbols   :
//************************************
void BSSlotsContainer::BuildTicket(GTArray<int> slotSymbols)
{
#ifdef GT_DEBUG
	GTLogManager::SLogFormatComment("<------------- slot symbols (visible part current 3X5 reels)----------->");	
	GTLogManager::SLogFormatComment(slotSymbols.ToString());
#endif

	//based on real slot symbols to create fake tickets to all reels; 
	//make Fake reels(top & bottom invisible)

	//for exmaple:
	//	2, 3, 5, 6, 5,
	//	5, 5, 5, 8, 1,
	//	4, 3, 3, 3, 3
	//  make 5 reels
	//  reel1: 0, 2, 5, 4, 0
	//  reel2: 0, 3, 5, 3, 0
	// and so on
	GTDictionary<int, GTArray<int>* > reeltickets;

	//initialize
	for(int reelIndex = 0; reelIndex < m_reelColumns.Count(); reelIndex++)
	{
		GTArray<int>* pTickets = new GTArray<int>();
		pTickets->AddToTail(0);	//make fake symbols for top invisible symbols
		reeltickets.Add(reelIndex, pTickets);
	}

	//add reel symbols;
	for(int i = 0; i < slotSymbols.Length(); i++)
	{
		int reelID = i % m_reelColumns.Count();
		int slotSymbolValue = slotSymbols[i];

		GTArray<int>* pTickets = NULL;
		reeltickets.GetValueByKey(reelID, pTickets);		
		pTickets->AddToTail(slotSymbolValue);
	}

	//make fake symbols for top and bottom invisible symbols;
	for(int reelIndex = 0; reelIndex < m_reelColumns.Count(); reelIndex++)
	{
		GTArray<int>* pTickets;
		reeltickets.GetValueByKey(reelIndex, pTickets);
		pTickets->AddToTail(0);		//make fake symbols for bottom invisible symbols

		m_reelColumns[reelIndex]->SetTicket(*pTickets);	//send it to every reel;

		delete pTickets;
	}
	m_slotsSymbols = slotSymbols;
}
// Create the sprite from the property tree node
bool BSWinlineLoader::CreateFromPropertyTreeNode(GTTreeNode *pTreeNode)
{
	if(NULL == pTreeNode)
	{
		return false;
	}


	bool res = false;
	GTString errorCode("");

	//load all winlines;  Note: from winline 1 -> n 
	int winlineID = 1;
	do 
	{
		//set reel name
		GTString winlineTag = PROPERTY_TAG_WINLINE;
		winlineTag.Append(GTString::From(winlineID));// + GTString::FormatFrom(id);
		GTTreeNode* pWinline = pTreeNode->GetChild(winlineTag.ToCharString());

		if(pWinline == NULL)
			break;

		GTArray<int> winlineSlotArray;	//winline slot define;
		pWinline->ValueToArrayInt(winlineSlotArray);

		if(m_winlineDict.KeyExists(winlineID))
		{
			m_winlineDict.Remove(winlineID);
			GTLogManager::SLogFormatWarning("Warning! new winline[%d] will replace old one!!", winlineID);
		}
		m_winlineDict.Add(winlineID, winlineSlotArray);
		winlineID++;		
	} while (true);


	//load paytable; from 1 -> n
	int wintableID = 1;
	do 
	{
		//set reel name
		GTString PayTableTag = PROPERTY_TAG_PAYTABLE;
		PayTableTag.Append(GTString::From(wintableID));// + GTString::FormatFrom(id);
		GTTreeNode* pPaytable = pTreeNode->GetChild(PayTableTag.ToCharString());

		if(pPaytable == NULL)
			break;

		GTArray<int> payTableValue;	//winline slot define;
		pPaytable->ValueToArrayInt(payTableValue);

		if(payTableValue.Length() < 2)
		{
			GTLogManager::SLogFormatError("Error! Paytable[%d] does not have 2 values!", wintableID);
		}
		else
		{
			int paytableID = payTableValue[0];
			int ptValue = payTableValue[1];
			if(m_paytableDict.KeyExists(paytableID))
			{
				m_paytableDict.Remove(paytableID);
				GTLogManager::SLogFormatWarning("Warning! new paytable[%d] will replace old one!!", wintableID);
			}
			m_paytableDict.Add(paytableID, ptValue);
		}
		wintableID++;		
	} while (true);


	return res;
}
//************************************
// Method:    CheckBonusAndLock
// FullName:  BSSlotsContainer::CheckBonusAndLock
// Access:    protected 
// Returns:   bool
// Qualifier: depends on locked(2rd round) or not lock(1st round), to check bonus symbols and play respin or freespin
// Parameter: bool haveReelsLocked   :
//************************************
bool BSSlotsContainer::CheckBonusSymbolsAndLock(bool haveReelsLocked)
{
	int bonusMiniCount = 0;

	if(haveReelsLocked)	
	{
		//means to get final locked reels, this is 2rd round, which some reels had been locked 
		//in this round, even 1 reel should be lock and play;
		bonusMiniCount = 0;	
	}
	else
	{
		//this is 1st round, only bonus count larger than bonusMiniCount, 
		//then lock and play respin;
		 bonusMiniCount = 2;
	}

	bool haveNewLockReel = false;
	GTArray<int> newLockReelIDs;	//store all new lock reels
	
	//check bonus symbol;
	int bonusSymbolID = m_pTicketGenerator->GetBonusSymbolID();
	//GTArray<int> slotSymbols = m_pTicketGenerator->GetSlotSymbols();

	for(int i = 0; i < m_slotsSymbols.Length(); i++)
	{
		int reelID = i % m_reelColumnCount;
		int slotSymbolValue = m_slotsSymbols[i];

		//find bonus symbol, then add this reelID into dictionary for later lock;
		if(slotSymbolValue == bonusSymbolID)
		{
			if(!m_lockReelsDict.KeyExists(reelID))	
			{
				newLockReelIDs.Add(reelID);
			}
		}
	}

	if(newLockReelIDs.Length() < bonusMiniCount)
		return false;

	//initialize all new lock reels
	for(int i = 0; i < newLockReelIDs.Length(); i++)
	{
		m_lockReelsDict.Add(newLockReelIDs[i], NULL);
	}

	//build new respin for every one new lock reels
	for(int i = 0; i < newLockReelIDs.Length(); i++)
	{
		int reelID = newLockReelIDs[i];
		GTGameObject* pGameObject = GTGameObjectManager::Inst()->CreateGameObject(NULL, CTEXT("respin1"), CTEXT("SlotGame/Respin.property"));
		if(pGameObject)
		{
			//add new lock reel into dictionary;
			m_lockReelsDict.Remove(reelID);
			m_lockReelsDict.Add(reelID, pGameObject);

			//get every reel position
			BSReelColumn* reelColum = m_reelColumns[reelID];
			GTPoint2 reelPos = reelColum->GetGameObjectPosition();		

			//set respin to there and play animation
			BSRespin* pRespin = (BSRespin*)(pGameObject->GetBehaviour(CTEXT("BSRespin")));
			if(pRespin)
			{			
				pRespin->SetGameObjectPosition(reelPos);

				GTLogManager::SLogFormatTrace("repsin lock: (%f, %f)  -> playing lock animtion", reelPos.x, reelPos.y);
				pRespin->PlayLockAnimation();
				haveNewLockReel = true;
			}
		}
	}
	return haveNewLockReel;
}