//////////////////////////////////////////////////////////////////////////////
//
// File: AVP_Player_Quest.cpp
//
// (AJK - 13.10.2008) Created
//
// Copyright (C) 2008 Rebellion, All Rights Reserved.
//
//////////////////////////////////////////////////////////////////////////////

#include "Core/Asura.h"

// This file's header.
#include "Entity/PlayerInfo/AVP_Player_Quest.h"

// Asura
#include "ChunkSystem/Asura_Chunk_Stream.h"
#include "Debugging/Asura_Assert.h"
#include "Network/Asura_Guid.h"

// AVP
#include "Entity/ObjectiveSystem/PlayerObjective/AVP_ServerEntity_PlayerObjective.h"

const int iAVP_PLAYERQUEST_CHUNK_VERSION = 3;

AVP_Player_Quest::AVP_Player_Quest()
: m_uObjectivesCount(0)
, m_uCompletedObjectivesCount(0)
{
	InitObjectivesList();
}

void AVP_Player_Quest::InitObjectivesList()
{
	for(int i=0; i<MAX_OBJECTIVES; ++i)
	{
		m_auObjectivesList[i]            = ASURA_GUID_UNREGISTERED;
		m_auCompletedObjectivesList[i]   = ASURA_GUID_UNREGISTERED;
	}
}

bool AVP_Player_Quest::IsObjectiveInList(Asura_Guid uObjective)
{
	for( u_int u=0; u<m_uObjectivesCount; ++u)
	{
		if(uObjective == m_auObjectivesList[u])
		{
			return true;
		}
	}
	return false;
}

void AVP_Player_Quest::AddToObjectivesList(Asura_Guid uObjective)
{
	if( m_uObjectivesCount < MAX_OBJECTIVES - 1 )
	{
		m_auObjectivesList[m_uObjectivesCount++] = uObjective;
	}
	else
	{
		Asura_Assert(false, "Reached Max objectives");
	}
}

void AVP_Player_Quest::AddToCompletedObjectivesList(Asura_Guid uObjective)
{
	if( m_uCompletedObjectivesCount < MAX_OBJECTIVES - 1 )
	{
		m_auCompletedObjectivesList[m_uCompletedObjectivesCount++] = uObjective;
	}
	else
	{
		Asura_Assert(false, "Reached Max objectives");
	}
}

Asura_Guid AVP_Player_Quest::GetLatestNonCompletedObjective() const
{
	for( int i = m_uObjectivesCount-1; i >= 0; --i)
	{
		const AVP_ServerEntity_PlayerObjective* pxObjective = AVP_ServerEntity_PlayerObjective::FindEntity( m_auObjectivesList[i] );
		if ( pxObjective && !pxObjective->IsCompleted())
		{
			return m_auObjectivesList[i];
		}
	}
	return ASURA_GUID_UNREGISTERED;
}

Asura_Guid AVP_Player_Quest::GetRankedObjective ( u_int iRank ) const
{
	Asura_Guid uRankedObjective = ASURA_GUID_UNREGISTERED;
	if ( ( uRankedObjective = GetRankedNonCompletedObjective( iRank ) ) != ASURA_GUID_UNREGISTERED ) return uRankedObjective;
	return GetRankedCompletedObjective( iRank - GetNonCompletedObjectiveCount( ));
}

u_int AVP_Player_Quest::GetNonCompletedObjectiveCount() const
{
	u_int u = 0;
	for( u_int u2 = 0; u2 < m_uObjectivesCount; ++u2)
	{
		const AVP_ServerEntity_PlayerObjective* pxObjective = AVP_ServerEntity_PlayerObjective::FindEntity( m_auObjectivesList[u2] );
		if ( pxObjective && !pxObjective->IsCompleted())
		{
			++u;
		}
	}
	return u;
}

Asura_Guid AVP_Player_Quest::GetRankedNonCompletedObjective( u_int iRank )const
{
	u_int u = 0;
	for( int i = m_uObjectivesCount-1; i >= 0; --i)
	{
		const AVP_ServerEntity_PlayerObjective* pxObjective = AVP_ServerEntity_PlayerObjective::FindEntity( m_auObjectivesList[i] );
		if ( pxObjective )
		{
			if (!pxObjective->IsCompleted() && u++ == iRank )
			{
				return m_auObjectivesList[i];
			}
		}
	}
	return ASURA_GUID_UNREGISTERED;
}

Asura_Guid AVP_Player_Quest::GetRankedCompletedObjective( u_int iRank )const
{
	if ( iRank < m_uCompletedObjectivesCount)
	{
		return m_auCompletedObjectivesList[ m_uCompletedObjectivesCount - 1 - iRank ];
	}

	return ASURA_GUID_UNREGISTERED;
}

AVP_Player_Quest& AVP_Player_Quest::operator=(const AVP_Player_Quest& xOther)
{
	m_uObjectivesCount          = xOther.m_uObjectivesCount;
	m_uCompletedObjectivesCount = xOther.m_uCompletedObjectivesCount;

	for( int i=0; i < MAX_OBJECTIVES; ++i)
	{
		m_auObjectivesList[i] = xOther.m_auObjectivesList[i];
	}

	for( int i=0; i < MAX_OBJECTIVES; ++i)
	{
		m_auCompletedObjectivesList[i] = xOther.m_auCompletedObjectivesList[i];
	}

	return *this;
}

void AVP_Player_Quest::WriteToChunkStream( Asura_Chunk_Stream& xStream ) const
{
	int iVersion = iAVP_PLAYERQUEST_CHUNK_VERSION;
	xStream << iVersion;

	// Objective guids
    xStream << m_uObjectivesCount;
	for( u_int u = 0; u < m_uObjectivesCount; ++u )
	{
		xStream << m_auObjectivesList[ u ];
	}

	xStream << m_uCompletedObjectivesCount;
	for( u_int u = 0; u < m_uCompletedObjectivesCount; ++u )
	{
		xStream << m_auCompletedObjectivesList[ u ];
	}
}

void AVP_Player_Quest::ReadFromChunkStream( Asura_Chunk_Stream& xStream )
{
	int iVersion = 0;
	xStream >> iVersion;
	
	if ( iVersion == iAVP_PLAYERQUEST_CHUNK_VERSION )
	{
		// Objective guids
		xStream >> m_uObjectivesCount;
		for( u_int u = 0; u < m_uObjectivesCount; ++u )
		{
			xStream >> m_auObjectivesList[ u ];
		}

		xStream >> m_uCompletedObjectivesCount;
		for( u_int u = 0; u < m_uCompletedObjectivesCount; ++u )
		{
			xStream >> m_auCompletedObjectivesList[ u ];
		}
	}
	else if ( iVersion == 2 )
	{
		// Objective guids
		u_int uPrimaryObjectivesCount;
		xStream >> uPrimaryObjectivesCount;
		for( u_int u = 0; u < uPrimaryObjectivesCount; ++u )
		{
			xStream >> m_auObjectivesList[ u ];
		}

		u_int uSecondaryObjectivesCount;
		xStream >> uSecondaryObjectivesCount;
		for( u_int u = uPrimaryObjectivesCount; u < uPrimaryObjectivesCount + uSecondaryObjectivesCount; ++u )
		{
			xStream >> m_auObjectivesList[ u ];
		}

		m_uObjectivesCount = uPrimaryObjectivesCount + uSecondaryObjectivesCount;

		u_int uCompletedPrimaryObjectivesCount;
		xStream >> uCompletedPrimaryObjectivesCount;
		for( u_int u = 0; u < uCompletedPrimaryObjectivesCount; ++u )
		{
			xStream >> m_auCompletedObjectivesList[ u ];
		}

		u_int uCompletedSecondaryObjectivesCount;
		xStream >> uCompletedSecondaryObjectivesCount;
		for( u_int u = uCompletedPrimaryObjectivesCount; u < uCompletedPrimaryObjectivesCount + uCompletedSecondaryObjectivesCount; ++u )
		{
			xStream >> m_auCompletedObjectivesList[ u ];
		}

		m_uCompletedObjectivesCount = uCompletedPrimaryObjectivesCount + uCompletedSecondaryObjectivesCount;
	}
	else if ( iVersion == 1 )
	{
		// Objective guids
		u_int uPrimaryObjectivesCount;
		xStream >> uPrimaryObjectivesCount;
		for( u_int u = 0; u < uPrimaryObjectivesCount; ++u )
		{
			xStream >> m_auObjectivesList[ u ];
		}

		u_int uSecondaryObjectivesCount;
		xStream >> uSecondaryObjectivesCount;
		for( u_int u = uPrimaryObjectivesCount; u < uPrimaryObjectivesCount + uSecondaryObjectivesCount; ++u )
		{
			xStream >> m_auObjectivesList[ u ];
		}

		m_uObjectivesCount = uPrimaryObjectivesCount + uSecondaryObjectivesCount;
	}
}