//====== Namespace UA
if(!window.UA) 	UA = {};

//=== Class StaticUser
UA.StaticUser = Class.create();
//=== Class StaticUser

//=== Class User
UA.User = Class.create();
/*    static members	*/
//-------------------------------------------------------------
/**
 * @private
 * holds references to all requests sent by this instance
 **/
UA.User.Requests = [];
/**
 * @private
 * holds all method names that are used with the object's handler
 **/
UA.User.Methods =   { GETUSER:      "GetBasicUserDetails"   //FishHook
                    , GETUSERDETAILS: "GetUserDetails"      //Diamond
                    , GETALLSCORES: "GetAllScores"
                    , GETUSERGAMES:	"GetUserGames"          //1400::"UserGames"
                    , HASFREETRIAL: "HasFreeTrial"
                    , ISSUBSCRIBED: "IsSubscribed"
                    , ISAUTHORIZED: "IsAuthorized" //Harpoon
                    , GETSUBSCRIBEDCHANNELS: "GetSubscribedChannels"    //Not in use
                    , GETCURRENTPERMITTEDSKUS: "GetCurrentPermittedSKUs" //Harpoon
                    , GETPLANNEDPERMITTEDSKUS: "GetPlannedPermittedSKUs" //Harpoon
                    , GETPACKAGEEXPIRATIONUTCDATE: "GetPackageExpirationUTCDate" //Harpoon
                    , ISNICKNAMEAVAILABLE: "IsNicknameAvailable"
                    , GETAVATAR: "GetAvatar"
                    , GETAVATARSTUDIO: "GetAvatarStudio"
                    , GETHIGHESTMEDAL: "GetHighestMedal"
					, GETUSERRECENTGAMES: "GetUserRecentGames"  //Not in use
                    , GETPERSONADATABYNICKNAME : "GetPersonaDataByNickname"
                    , GETDATA    : "GetData"
                    , GET_OBERON_CLIENT_USERID : "GetOberonClientUserId"
                    , GET_PARTNER_PROGRAM_ID: "GetPartnerProgramId"
                    }
/*    members			*/
//-------------------------------------------------------------
UA.User.USER_HANDLER_URL = "UNSET-VALUE";
UA.User.USER_LOGIN_REDIRECT_URL = "UNSET-VALUE";
UA.User.POST_DATA_REDIRECT_URL = "UNSET-VALUE";

UA.User.LOGGED_IN = "LoggedIn";
UA.User.ANONYMOUS = "Anonymous";
/*	  Constructors		*/
//-------------------------------------------------------------
/**
 * public constructor.
 * Sends an ISLOGGEDIN request if the user is logged in to populate user details.
 * No parameters: UserGuid is taken from cookie by Jast.Request.
 **/
UA.User.prototype.initialize = function(){
    this.log = new Log4Js.Logger("[UA.User]");
    this.params = {"Period":"", "Sku":"", "Mode":""};
}

//function IsLoggedOn(reloadCookies): checks if the user has unclassified cookie.
//      dontReloadCookies: avoid reload cookies and rebuild Clearance or not.
// You can also invoke this method without parameters: UA.User.prototype.IsLoggedOn()
UA.User.prototype.IsLoggedOn = function(dontReloadCookies){
    if(dontReloadCookies == undefined || dontReloadCookies == false)
        Clearance.refresh();
    return Clearance.hasUnclassified();
}

//function isGuest(reloadCookies): checks if the user is authenticated as guest.
//      dontReloadCookies: reloadCookies reloading cookies and rebuild Clearance or not.
// You can also invoke this method without parameters: UA.User.prototype.isGuest()
UA.User.prototype.isGuest = function(dontReloadCookies){
    return ( !UA.User.prototype.IsLoggedOn(dontReloadCookies) || Clearance.isGuest() );
}

UA.User.prototype.LogOff = function(){ 
    Clearance.forget( Url.relativeUrl( { withClearanceParams: false, withHereParams: true } ) ); 
}

/*    inner class		*/
//-------------------------------------------------------------

/* --- start inner class : UA.User.UserRequest   --*/
/**
 * @class 
 * The goal of this class is to allow multiple calls on the same User object-instance,
 * and aid in making the Asyncronous work as transparent as possible. 
 * 
 * This inner class extends the "abstract"-class UI.Request
 *
 * ...
 **/
UA.User.UserRequest = Class.createSubclass("UA.Request");
UA.User.UserRequest.prototype = UA.Request.AsPrototype()

UA.User.UserRequest.prototype.initialize = function userReqCTor(oUser, fSuccessCallback, fFailCallback, fTimeoutCallback){
	this.boss = this.log.boss = oUser;
	this.url = this.boss.USER_HANDLER_URL;
    this.parameters = Object.extend({}, this.boss.params);
}

UA.User.UserRequest.prototype.addParameter = function(key, val){
    this.parameters[key] = val;
}

/* --- end inner class : UA.User.UserRequest   --*/

// FishHook version of GetDetails.
// Returns basic data: Nickname, avatar ID, avatar name, avatar URL.
UA.User.prototype.GetDetails = function(fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
	r.parameters.MethodName = UA.User.Methods.GETUSER;
	r.apply();
}

// Diamond version of GetDetails.
// Returns comprehensive data: nickname, gender, birthday splitted to day, 
// month and year, country, region, acceptedTermsAndConditions (True/False), 
// termsAndConditionsVersion, emailOptIn (send news letters - True/False), zipCode. 
UA.User.prototype.GetUserDetails = function(fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
	r.parameters.methodName = UA.User.Methods.GETUSERDETAILS;
	r.apply();
}

/**
 * Gets the user recent games along with their details and the user achievements.
 * Returns the SKUs and optionally their top scores and the user's high score, rank and last play time.
 *  Sample of use:
 *      var u = new UA.User()
 *      u.params.maxGames = 20; //optional parameter (the default is all games)
 *      u.params.bitmask = 15;  //optional parameter (the default is all fields)
 *      u.GetUserGames(GetUserGames_onSuccess, GetUserGames_onFailer, OnTimeout);
 *
 *
 * @param {function(result)} fSuccess
 *	The callback function that is expected to be called on success with 'request.result.Data' as a 
 *  as passed argument.
 * 
 * @param {function(result)} fFailure
 *	The callback function that is expected to be called on failure with 'request.result' as the 
 *  passed argument.
 * 
 * @param {function(result)} fTimeout
 *	The callback function that is expected to be called on timeout with 'request' as the 
 *  passed argument.
 * 
 **/
 UA.User.prototype.GetUserGames = function(fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
	r.parameters.methodName = UA.User.Methods.GETUSERGAMES;
	r.apply();
}

UA.User.prototype.GetUserRecentGames = function(fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
	r.parameters.methodName = UA.User.Methods.GETUSERRECENTGAMES;
	r.apply();
}

// Diamond.
// Tells whether the given nickname is available for the given community (the community is retrieved according to the channel code).
// In addition, a profanity check is being performed, for which the nickname language is needed.
// Returns true if nickname is valid and available for use. False otherwise.
UA.User.prototype.IsNicknameAvailable = function(sNickname, sChannel, sLanguage, fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
    r.parameters.Nickname = sNickname;
    r.parameters.Channel = sChannel;
    r.parameters.Language = sLanguage;
	r.parameters.methodName = UA.User.Methods.ISNICKNAMEAVAILABLE;
	r.apply();
}

// Avatar sizes - matches Avatar.Dimentions class of Application Libraries.
UA.User.Avatar = {};
UA.User.Avatar.Size = {};
UA.User.Avatar.Size.Size150x200 = "Size150x200";
UA.User.Avatar.Size.Size65x87 = "Size65x87";
UA.User.Avatar.Size.Size86x115 = "Size86x115";
UA.User.Avatar.Size.Size98x131 = "Size98x131";
UA.User.Avatar.Size.Size124x165= "Size124x165"; 
UA.User.Avatar.Size.Size24x24 =  "Size24x24";  
UA.User.Avatar.Size.Size48x48 = "Size48x48";      

// Get avatar html object according to the specified size.
// Returns html tag object.
UA.User.prototype.GetAvatar = function(eSize, fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
    r.parameters.Size = eSize;
	r.parameters.methodName = UA.User.Methods.GETAVATAR;
	r.apply();
}

// Get avatar studio html object according to the specified size.
// Returns html tag object.
UA.User.prototype.GetAvatarStudio = function(fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
	r.parameters.methodName = UA.User.Methods.GETAVATARSTUDIO;
	r.apply();
}

// Get user's highest medal.
// Returns game sku and user ranking.
UA.User.prototype.GetHighestMedal = function(fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
	r.parameters.methodName = UA.User.Methods.GETHIGHESTMEDAL;
	r.apply();
}

// Returns a persona's data by nickname : Avatar-object, Score, Rating ,Highest-Medal
UA.User.prototype.GetPersonaDataByNickname = function(nickname, avatarSize, sku, fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
    r.parameters.Nickname   = nickname;
    r.parameters.AvatarSize = avatarSize;
    r.parameters.Sku = sku;
	r.parameters.methodName = UA.User.Methods.GETPERSONADATABYNICKNAME;
	r.apply();
}

UA.User.ReportAbuse = function(abusingNickname, description, utcTime, retURL){
    var formReportAbuse = document.createElement("form");
	formReportAbuse.setAttribute("method", "POST");
	formReportAbuse.setAttribute("action", UA.User.POST_DATA_REDIRECT_URL);

	formReportAbuse.appendChild(CreateHiddenInput("abusingNickname", abusingNickname));	
	formReportAbuse.appendChild(CreateHiddenInput("description", description));
	formReportAbuse.appendChild(CreateHiddenInput("utcTime", utcTime));
	formReportAbuse.appendChild(CreateHiddenInput("retURL", retURL));
	
	formReportAbuse.appendChild(CreateHiddenInput("methodName", "ReportAbuse"));
	
	document.body.insertBefore(formReportAbuse, null);
	formReportAbuse.submit();
}

//-------------------------------------------------------------
/**
 * Default failure handler for all requests
 * Possible to be overriden in projectile code
 *
 * @type function
 **/
UA.User.prototype.defaultOnFailior = null;
/**
 * Default timeout handler for all requests
 * Possible to be overriden in projectile code
 *
 * @type function
 **/
UA.User.prototype.defaultOnTimeout = null;

/**
 * Overrides the Object.toString()
 **/
UA.User.prototype.toString = function(){
    return "[User: " + this.Nickname + "]";
}
/**
 * Gets a UserRequest object, ready to be filled with parameters, and be applied.
 **/
UA.User.prototype.getUserRequest = function(fSuccessCallback){
	var r = new UA.User.UserRequest(this,fSuccessCallback);

	r.id = UA.User.Requests.length;
	UA.User.Requests[ r.id ] = r;

	return r;
}

// User Login send the POST data for login
UA.User.prototype.LoginRedirect = function(email, password, isPasswordRemember, channel){
	var formLogin = document.createElement("form");
	formLogin.setAttribute("method", "POST");
	formLogin.setAttribute("action", UA.User.prototype.USER_LOGIN_REDIRECT_URL);
	
	formLogin.appendChild(CreateHiddenInput("email", email));
	formLogin.appendChild(CreateHiddenInput("password", password));
	formLogin.appendChild(CreateHiddenInput("remember", isPasswordRemember));
	formLogin.appendChild(CreateHiddenInput("channel", channel));
	
	formLogin.appendChild(CreateHiddenInput("methodName", "Login"));
	
	document.body.insertBefore(formLogin, null);
	formLogin.submit();
}

// User Login As Guest send the POST data for login
UA.User.prototype.LoginAsGuestRedirect = function(channel){
	var formLogin = document.createElement("form");
	formLogin.setAttribute("method", "POST");
	formLogin.setAttribute("action", UA.User.prototype.USER_LOGIN_REDIRECT_URL);
	
	formLogin.appendChild(CreateHiddenInput("channel", channel));
	
	formLogin.appendChild(CreateHiddenInput("methodName", "LoginAsGuest"));
	
	document.body.insertBefore(formLogin, null);
	formLogin.submit();
}

UA.User.SendForgotMail = function(email, channel){
    var formLogin = document.createElement("form");
	formLogin.setAttribute("method", "POST");
	formLogin.setAttribute("action", UA.User.prototype.USER_LOGIN_REDIRECT_URL);
	
	formLogin.appendChild(CreateHiddenInput("email", email));
	formLogin.appendChild(CreateHiddenInput("channel", channel));
	
	formLogin.appendChild(CreateHiddenInput("methodName", "SendForgotMail"));
	
	document.body.insertBefore(formLogin, null);
	formLogin.submit();
}

//This method facilitate the invocation of one or more processing methods (handlers) as a batch
//That is the prefered way to invoke server-side processing methods
// methodsArr: an array of server-side methods (one or more) to be invoked.
// paramsList: a string of parameters for the methods in the format of "Param1:value1,Param2:value2", or null.
// OnSuccess The method return a <complex JASON> object like 
//              {"method1": {sub-jason1}, "method2": {sub-jason2}, "method3":{sub-jason3} ……,"methodN": {sub-jasonN} }  
// OnFailure The method return a JASON object like 
//  {{Status: '<Cause>' }, {Data: {<complex JASON>} } 
UA.User.prototype.GetData = function(methodsArr, paramsList, fSuccessCallback, fFailCallback, fTimeoutCallback){
	if(methodsArr.length == 0){
	    return;
	}
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
	r.parameters.methodName = UA.User.Methods.GETDATA;
	
	//Chaining the methods to invoke as one string
	var methodsStr = methodsArr[0];
	for(var i = 1 ; i < methodsArr.length ; i++)
	{
	    methodsStr += ( "," + methodsArr[i] );
	}
	r.parameters.MethodList = methodsStr;
	
  	//Adding the parameters that needs to be sent. 
  	if(paramsList != null)
  	{
  	    var paramsArr = paramsList.split(",");
	    for(var i = 0 ; i < paramsArr.length ; i++)
	    {
	        var kNv = paramsArr[i].split(":");  //key and value
	        r.addParameter(kNv[0], kNv[1]);
	    }
	}
	r.apply();
}