// Look up a transaction by transaction number and see if it is in the ledger.
// If it is, return a pointer to it, otherwise return NULL.
OTTransaction * OTLedger::GetTransaction(long lTransactionNum)
{
	// See if there's something there with that transaction number.
	mapOfTransactions::iterator it = m_mapTransactions.find(lTransactionNum);
	
	if ( it == m_mapTransactions.end() )
	{
		// not found.
		return NULL;
	}
	// Found it!
	else 
	{
		OTTransaction * pTransaction = (*it).second;
		
		OT_ASSERT((NULL != pTransaction));
		
		if (pTransaction->GetTransactionNum() == lTransactionNum)
			return pTransaction;
		else 
			OTLog::vError("Expected transaction number %ld, but found %ld on the list instead. Bad data?\n",
						  lTransactionNum, pTransaction->GetTransactionNum());
	}
	
	return NULL;
}
// Look up a transaction by transaction number and see if it is in the ledger.
// If it is, return a pointer to it, otherwise return NULL.
OTTransaction * OTLedger::GetTransaction(long lTransactionNum)
{
	// loop through the items that make up this transaction
	
//  OTLog::vError("OTLedger::GetTransaction: Checking ledger for trans %ld. COUNT: %d \n", lTransactionNum, GetTransactionCount());
    
	for (mapOfTransactions::iterator ii = m_mapTransactions.begin(); ii != m_mapTransactions.end(); ++ii)
	{
		OTTransaction * pTransaction = (*ii).second;
		OT_ASSERT(NULL != pTransaction);
		
//      OTLog::vError("OTLedger::GetTransaction: Looping. Currently on trans %ld \n", pTransaction->GetTransactionNum());
        
		if (pTransaction->GetTransactionNum() == lTransactionNum)
        {
//          OTLog::vOutput(5, "OTLedger::GetTransaction: Returning transaction# %ld \n", lTransactionNum);
            
			return pTransaction;
        }
//		else // this was for debugging only. It's actually normal for non-matching numbers to be on this list.
//			OTLog::vOutput(5"Expected transaction number %ld, but found %ld on the list instead. Bad data?\n",
//						  lTransactionNum, pTransaction->GetTransactionNum());
	}
	
//        OTLog::Error("OTLedger::GetTransaction: Returning NULL \n");

	return NULL;
}
bool OTLedger::AddTransaction(OTTransaction & theTransaction)
{
	// See if there's something else already there with the same transaction number.
	mapOfTransactions::iterator it = m_mapTransactions.find(theTransaction.GetTransactionNum());
	
	// If it's not already on the list, then add it...
	if ( it == m_mapTransactions.end() )
	{
		m_mapTransactions[theTransaction.GetTransactionNum()] = &theTransaction;
		return true;
	}
	// Otherwise, if it was already there, log an error.
	else 
	{
		OTLog::vError("Attempt to add Transaction to ledger when already there for that number: %ld\n",
					  theTransaction.GetTransactionNum());
	}
	
	return false;
}
// LoadContract will call this function at the right time.
// return -1 if error, 0 if nothing, and 1 if the node was processed.
int OTLedger::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
{	
	OTString strKeyName;
	OTString strKeyValue;
	
	OTString strTransaction;
	OTASCIIArmor ascTransaction;
	
	if (!strcmp("accountLedger", xml->getNodeName()))
	{	
		OTString strType, strLedgerAcctID, strLedgerAcctServerID, strUserID;
		
		strType = xml->getAttributeValue("type");
		
		if (strType.Compare("message"))
			m_Type = OTLedger::message;
		else if (strType.Compare("inbox"))
			m_Type = OTLedger::inbox;
		else if (strType.Compare("outbox"))
			m_Type = OTLedger::outbox;
		else if (strType.Compare("nymbox"))
			m_Type = OTLedger::nymbox;
		else
			m_Type = OTLedger::error_state;
	
		m_strVersion			= xml->getAttributeValue("version");	
		strLedgerAcctID			= xml->getAttributeValue("accountID"); 
		strLedgerAcctServerID	= xml->getAttributeValue("serverID");
		strUserID				= xml->getAttributeValue("userID");
		
		OTIdentifier ACCOUNT_ID(strLedgerAcctID), SERVER_ID(strLedgerAcctServerID), USER_ID(strUserID);
		
		SetPurportedAccountID(ACCOUNT_ID);
		SetPurportedServerID(SERVER_ID);
		SetUserID(USER_ID);
		
		OTLog::vOutput(2, "Loaded account ledger of type \"%s\", version: %s\n",
//				"accountID:\n%s\n userID:\n%s\n serverID:\n%s\n----------\n", 
				strType.Get(),
				m_strVersion.Get()
//				strLedgerAcctID.Get(), strUserID.Get(), strLedgerAcctServerID.Get()
				);
			
		// Since we just loaded this stuff, let's verify it.
		// We may have to remove this verification here and do it outside this call.
		// But for now...
		if (VerifyContractID())
			return 1;
		else {
			return -1;
		}

	}
	else if (!strcmp("transaction", xml->getNodeName()))
	{
		// go to the next node and read the text.
		xml->read();
		
		if (EXN_TEXT == xml->getNodeType())
		{
			// the ledger contains a series of transactions.
			// Each transaction is initially stored as an OTASCIIArmor string.
			ascTransaction.Set(xml->getNodeData());		// Put the ascii-armored node data into the ascii-armor object
			ascTransaction.GetString(strTransaction);	// Decode that into strTransaction, so we can load the transaction object from that string.
			OTTransaction * pTransaction = new OTTransaction(GetUserID(), GetPurportedAccountID(), GetPurportedServerID());
			
			// If we're able to successfully base64-decode the string and load it up as
			// a transaction, then let's add it to the ledger's list of transactions
			if (pTransaction && pTransaction->LoadContractFromString(strTransaction)
				&& pTransaction->VerifyContractID())
				// I responsible here to call pTransaction->VerifyContract() since
				// I am loading it here and adding it to the ledger. (So I do.)
			{
				m_mapTransactions[pTransaction->GetTransactionNum()] = pTransaction;
//				OTLog::Output(5, "Loaded transaction and adding to m_mapTransactions in OTLedger\n");
			}
			else {
				OTLog::Error("ERROR: loading transaction in OTLedger::ProcessXMLNode\n");
				if (pTransaction)
				{
					delete pTransaction;
					pTransaction = NULL;
				}
				return (-1);
			}

		}
		else {
			OTLog::Error("Error in OTLedger::ProcessXMLNode: transaction without value.\n");
			return (-1); // error condition
		}
		
		return 1;
	}
	
	return 0;
}