//////////////////////////////////////////////////////////////////////////////
//
// Asura_Xbox360_Friends.cpp
//
// Copyright (c) 2008 Rebellion. All rights reserved.
//
// Description:
//
//     wrapper for 360 friends API
//
//////////////////////////////////////////////////////////////////////////////

// I N C L U D E S ///////////////////////////////////////////////////////////

#include "Core/Asura.h"

#ifdef ASURA_SUPPORT_LOBBY

// This file's header.
#include "Network/Online/Asura_Xbox360_Friends.h"

// Asura independent 
#include "Core/Asura_Maths.h"

// Asura 360
#include "Core/Asura_Xbox360_OS.h"


// C O N S T A N T S /////////////////////////////////////////////////////////
static const u_int uASURA_XBOX360_MAX_FRIENDS = 100;

// S T A T I C   C L A S S   D A T A /////////////////////////////////////////
XUID* Asura_Xbox360_Friends::s_pxFriendsXUIDs;
u_int Asura_Xbox360_Friends::s_uNumFriends;

void Asura_Xbox360_Friends::Initialise()
{
	Asura_Assert(!s_pxFriendsXUIDs, "already allocated");
	s_pxFriendsXUIDs = new XUID[uASURA_XBOX360_MAX_FRIENDS + 1];	// first one is self
	// write our own xuid to the first entry
#ifdef ASURA_ASSERT
	DWORD uRet = 
#endif
		XUserGetXUID(Asura_Xbox360_OS::GetActivePlayerIndex(), s_pxFriendsXUIDs);
	Asura_Assert(uRet == ERROR_SUCCESS, "XUserGetXUID failed");

	Refresh();
}

void Asura_Xbox360_Friends::Shutdown()
{
	delete[] s_pxFriendsXUIDs;
	s_pxFriendsXUIDs = NULL;
	s_uNumFriends = 0;
}

void Asura_Xbox360_Friends::Refresh()
{
	if (!s_pxFriendsXUIDs)
	{
		// Friends list changed in an offline mode; we will get an up do date list when we initialise the system.
		return;
	}

	DWORD uError;
	DWORD uNumResults;
	DWORD uBufferSize;
	HANDLE xEnum = INVALID_HANDLE_VALUE;

	XONLINE_FRIEND* pxFriends;

	// call the friends reading function to set the needed HANDLE and to return 
	// the size needed for the buffer to pass to XEnumerate.
	uError = XFriendsCreateEnumerator
		(
		Asura_Xbox360_OS::GetActivePlayerIndex(),	// user who's friends we want
		0,                      					// starting index
		uASURA_XBOX360_MAX_FRIENDS, 				// max friends
		&uBufferSize,								// Size of buffer needed to enumerate
		&xEnum										// Handle to created enumerator
		);

	if (uError != ERROR_SUCCESS)
	{
		Asura_Assertf(false, ("XFriendsCreateEnumerator failed 0x%x", uError));
		return;
	}

	// allocate space for results to be returned by XEnumerate
	pxFriends = reinterpret_cast<XONLINE_FRIEND*>(new u_char[uBufferSize]);
	uError = XEnumerate
		(
		xEnum,
		pxFriends,
		uBufferSize,
		&uNumResults,  	// pcItemsReturned
		NULL        	// pOverlapped
		);

	// ensure we won't overflow our global friends buffer
	Asura_Assert(uNumResults <= uASURA_XBOX360_MAX_FRIENDS, "more friends than we specified");
	uNumResults = Asura_Maths::Min(static_cast<u_int>(uNumResults), uASURA_XBOX360_MAX_FRIENDS);

	// Process pxFriends
	if (uError == ERROR_SUCCESS)
	{
		for (u_int u = 0; u < uNumResults; ++u)
		{
			s_pxFriendsXUIDs[u + 1] = pxFriends[u].xuid;
		}

		s_uNumFriends = uNumResults;
	}

	CloseHandle(xEnum);
	delete [] pxFriends;
}

bool Asura_Xbox360_Friends::ShowFriendsGUI()
{
	return XShowFriendsUI(Asura_Xbox360_OS::GetActivePlayerIndex()) == ERROR_SUCCESS;
}

bool Asura_Xbox360_Friends::IsPlayerAFriend(XUID xXuid)
{
	for (u_int u = 0; u < s_uNumFriends; ++u)
	{
		if (s_pxFriendsXUIDs[u + 1] == xXuid)
		{
			return true;
		}
	}
	return false;
}

const XUID* Asura_Xbox360_Friends::GetFriendsList()
{
	Asura_Assert(s_pxFriendsXUIDs, "GetFriendsList() called while uninitialised");
	// don't include self, i.e. start at 2nd entry
	return s_pxFriendsXUIDs ? s_pxFriendsXUIDs + 1 : 0;
}

const XUID* Asura_Xbox360_Friends::GetFriendsListIncludingSelf()
{
	Asura_Assert(s_pxFriendsXUIDs, "GetFriendsList() called while uninitialised");
	return s_pxFriendsXUIDs;
}

u_int Asura_Xbox360_Friends::GetNumFriends()
{
	Asura_Assert(s_pxFriendsXUIDs, "GetFriendsList() called while uninitialised");
	return s_uNumFriends;
}

u_int Asura_Xbox360_Friends::GetNumFriendsIncludingSelf()
{
	Asura_Assert(s_pxFriendsXUIDs, "GetFriendsList() called while uninitialised");
	return s_uNumFriends + 1;
}

#endif // #ifdef ASURA_SUPPORT_LOBBY
