// DWBS ------------------------------------------------------------------ DWBS
//
// PLATFORM		: ALL
// PRODUCT		: BIT_DEMON
// VISIBILITY	: PUBLIC
//
// DWBS ------------------------------------------------------------------ DWBS

// PURPOSE: Client side interface to the profiles service. 

#ifndef BD_PROFILES_H
#define BD_PROFILES_H

#include <bdCore/bdCore.h>
#include <bdLobby/bdLobbyCommon/bdLobbyServicesCommon.h>
#include <bdLobby/bdLobbyErrorCode.h>
#include <bdLobby/bdLobbyCommon/bdQueryParams.h>
#include <bdLobby/bdLobbyCommon/bdQueryResult.h>

class bdRemoteTask;
class bdRemoteTaskManager;
class bdProfileInfo;


// Profiles operations
#define BD_PROFILE_CREATE			(1u)
#define BD_PROFILE_GET_PUBLIC_INFO	(2u)
#define BD_PROFILE_GET_PRIVATE_INFO	(3u)
#define BD_PROFILE_SET_PUBLIC_INFO	(4u)
#define BD_PROFILE_SET_PRIVATE_INFO	(5u)
#define BD_PROFILE_DELETE			(6u)
#define BD_PROFILE_EXISTS			(7u)

/// Client side interface to the DemonWare profile service. 
/// Create/update/delete and read public and private user profiles. The profiles
/// service is intended as a storage convenience for non-statistical player 
/// information.
/// Use the functions contained in this class to perform operations on the server.
/// Each of these function returns a task handle, which should be pumped to 
/// completion by calling its getStatus() function. When the status of a task is 
/// bdRemoteTask::BD_DONE, you can pass it into the bdProfiles::handleTask()
/// function. Once this is done, the error code for the task can be accessed via
/// bdProfiles::getErrorCode(). If you expect a result set to be returned from
/// the server as a result of the task you started, you must pass an instance of 
/// a bdQueryResult into bdProfiles::handleTask. The implementation must 
/// match the results you are expecting. Standard implementations are provided
/// for standard types of result sets. If the result set being returned contains
/// customized attributes, you will need a specialized implementation
/// of bdQueryResult.
class bdProfiles
{
	public:
		BD_DECLARE_NEW_AND_DELETE_OPERATORS		

		~bdProfiles();

		/// Create a profile.
		/// When creating a profile, you must provide the public information
		/// to be associated with the profile. You can add private information to 
		/// the profile later.
		/// \param controllerIndex[in] The controller index of the requestor.
		/// \param profileInfo[in]		The public profile info to be associated
		///								with the profile. This must be a derived
		///								instance of bdQueryParams, specialized for
		///								the customized profile attributes that have
		///								been configured for your title ID. If you 
		///								have not configured any public profile attributes,
		///								you can just pass in an instance of bdQueryParams.
		/// \return	A pointer to the task handle that should be pumped to completion,
		///			or BD_NULL if the operation could not be performed (message 
		///			could not be sent, or maximum number of tasks was exceeded).
		/// \note	When complete, the returned bdRemoteTask will specify:
		///			BD_NO_ERROR - on success. 
		///			BD_PROFILE_EXISTS - if a profile using this profileID already exists.
		///			BD_PARAM_MISMATCHED_TYPE - if the parameters serialized in profileInfo
		///			do not match those specified for this title.
		bdRemoteTask* createProfile(bdUByte8 controllerIndex,
									bdProfileInfo *const profileInfo);

		/// Retrieve the public info for the specified user profile.
		/// \param controllerIndex[in]	The controller index of the requestor.
		/// \param userID[in]			The userID to return profile information for.
		/// \return	A pointer to the task handle that should be pumped to completion,
		///			or BD_NULL if the operation could not be performed (message 
		///			could not be sent, or maximum number of tasks was exceeded).
		/// \note	When this task completes, you can obtain the result set by 
		///			invoking bdProfiles::handleTask(). An instance of a class
		///			derived from bdQueryResult, which matches the results
		///			expected from the server, should be passed into it to receive
		///			the results.
		/// \note	When complete, the returned bdRemoteTask will specify:
		///			BD_NO_ERROR - on success. 
		///			BD_NO_PROFILE_INFO_EXISTS - if no public profile info has been 
		///			defined for this user.
		bdRemoteTask* getPublicInfo(bdUByte8 controllerIndex, 
									bdOnlineUserID userID);

		/// Retrieve the private info for the local user, specified by controllerIndex.
		/// Private profile information can only be accessed by the owner of the profile.
		/// \param controllerIndex[in]	The controller index of the requestor, whose private
		///								profile information will be returned.
		/// \return	A pointer to the task handle that should be pumped to completion,
		///			or BD_NULL if the operation could not be performed (message 
		///			could not be sent, or maximum number of tasks was exceeded).
		/// \note	When this task completes, you can obtain the result set by 
		///			invoking bdProfiles::handleTask(). An instance of a class
		///			derived from bdQueryResult, which matches the results
		///			expected from the server, should be passed into it to receive
		///			the results.
		/// \note	When complete, the returned bdRemoteTask will specify:
		///			BD_NO_ERROR - on success. 
		///			BD_NO_PROFILE_INFO_EXISTS - if no private profile info has been 
		///			defined for this user.
		bdRemoteTask* getPrivateInfo(bdUByte8 controllerIndex); 

		/// Set/update the public info for a specified user profile.
		/// \param controllerIndex[in]	The controller index of the requestor.
		/// \param profileInfo[in]		An instance of a class derived from 
		///								bdQueryParams that represents the public 
		///								profile info.
		/// \return	A pointer to the task handle that should be pumped to completion,
		///			or BD_NULL if the operation could not be performed (message 
		///			could not be sent, or maximum number of tasks was exceeded).
		/// \note		A BD_PROFILE_INFO_UPDATED will be delivered to all friends.
		/// \note	When complete, the returned bdRemoteTask will specify:
		///			BD_NO_ERROR - on success. 
		///			BD_NO_PROFILE_INFO_EXISTS - if no public profile info has been 
		///			defined for this user.
		///			BD_PARAM_MISMATCHED_TYPE - the parameters serialized in profileInfo
		///			did match the types defined for this title.
		bdRemoteTask* setPublicInfo(bdUByte8 controllerIndex, 
									bdProfileInfo *const profileInfo);

		/// Set/update the private info for a specified local user.
		/// Private information can only be updated by the owner of the profile.
		/// \param controllerIndex[in]	The controller index of the requestor, who
		///								owns the profile.
		/// \param profileInfo[in]		An instance of a class derived from 
		///								bdQueryParams that represents the private 
		///								profile info.
		/// \return	A pointer to the task handle that should be pumped to completion,
		///			or BD_NULL if the operation could not be performed (message 
		///			could not be sent, or maximum number of tasks was exceeded).
		/// \note	When complete, the returned bdRemoteTask will specify:
		///			BD_NO_ERROR - on success. 
		///			BD_NO_PROFILE_INFO_EXISTS - if no private profile info has been 
		///			defined for this user.
		///			BD_PARAM_MISMATCHED_TYPE - the parameters serialized in profileInfo
		///			did match the types defined for this title.
		bdRemoteTask* setPrivateInfo(bdUByte8 controllerIndex, 
									 bdProfileInfo *const profileInfo);

		/// Delete a profile for a specified local user.
		/// Profiles can only be deleted by the owner of the profile.
		/// \param controllerIndex[in]	The controller index of the requestor, whose
		///								profile will be deleted.
		/// \return	A pointer to the task handle that should be pumped to completion,
		///			or BD_NULL if the operation could not be performed (message 
		///			could not be sent, or maximum number of tasks was exceeded).
		/// \note	When complete, the returned bdRemoteTask will specify:
		///			BD_NO_ERROR - on success. 
		bdRemoteTask* deleteProfile(bdUByte8 controllerIndex);

		/// Check if a profile for the specified user ID exists.
		/// \param controllerIndex[in]	The controller index of the requestor.
		/// \param userID[in]			The user ID to check for an existing profile.
		/// \return	A pointer to the task handle that should be pumped to completion,
		///			or BD_NULL if the operation could not be performed (message 
		///			could not be sent, or maximum number of tasks was exceeded).
		/// \note	When this task completes, you can obtain the result set by 
		///			invoking bdProfiles::handleTask(). An instance of 
		///			bdCheckProfileExistsResult, should be passed into it to receive 
		///			the result.
		/// \note	When complete, the returned bdRemoteTask will specify:
		///			BD_NO_ERROR - on success. 
		bdRemoteTask* checkProfileExists(bdUByte8 controllerIndex,
										 bdOnlineUserID userID);

		/// Handle a completed task. 
		/// This retrieves the error code returned from the server, and fills out
		/// a result set of data, if appropriate. The specified task must have 
		/// been created by this class. 
		/// If the task is expected to return results, the second parameter should
		/// be specified. bdQueryResult is the base-class for classes that handle
		/// result sets returned from the server. A class matching the standard
		/// result set for calls to bdProfiles::checkProfileExists is located in 
		/// the same directory as this class (bdCheckProfileExistsResult). 
		/// The format of results for other calls is non-standard, and depends 
		/// on this title ID's Matchmaking+ configuration. Special implementations
		//// of bdQueryResult must be used in these cases.
		/// \param remoteTask[in]	A pointer to the remote task to handle.
		/// \param queryResult[in]	An optional pointer to an object that handles 
		///							the expected type of result data.
		/// \return - True if the task was successfully handled.
		///			- False otherwise. Call bdProfiles::getErrorCode() to get the 
		///			  error condition.
		bdBool handleTask(const bdRemoteTask *remoteTask, 
						  bdQueryResult *queryResult = BD_NULL);

		/// Return the error code of the last operation that failed.
		/// \return The last error code
		bdLobbyErrorCode getErrorCode() const;

	protected:

		friend class bdLobbyServiceImpl;

		/// Constructs a profiles manager with the given task handler.
		/// Note: never call this constructor directly, use bdLobbyService::getProfiles() instead.
		/// \param remoteTaskManager[in] A pointer to the remote task manager that handles
		/// requests and replies
		bdProfiles(bdRemoteTaskManager *const remoteTaskManager);

		bdLobbyErrorCode m_errorCode;

		bdRemoteTaskManager *m_remoteTaskManager;

};

#endif // BD_PROFILES_H
