/// <summary>
 /// Assists with the validating and setting up for adding callbacks
 /// </summary>
 /// <param name="playerNumber">The Player Number</param>
 /// <returns>True, if valid. False, otherwise</returns>
 private bool AddCallbackHelper(int playerNumber, string callbackTypeName)
 {
     if (ValidatePlayerNumber(playerNumber, "Adding " + callbackTypeName + " Callback", XboxLiveOperationType.AddCallback))
     {
         if (!CurrentPlayers.ContainsKey(playerNumber))
         {
             var playerInfo = new XboxLivePlayerInfo()
             {
                 SignInCallbacks  = new List <UnityAction <XboxLiveUser, XboxLiveAuthStatus, string> >(),
                 SignOutCallbacks = new List <UnityAction <XboxLiveUser, XboxLiveAuthStatus, string> >()
             };
             this.CurrentPlayers.Add(playerNumber, playerInfo);
         }
         return(true);
     }
     return(false);
 }
        /// <summary>
        /// Signs in a player. Attempts sign in silently first then sign in.
        /// </summary>
        /// <param name="playerNumber">The player number</param>
        /// <param name="playerInfo">The player info of the the player being signed in</param>
        /// <returns>A Coroutine</returns>
        private IEnumerator SignInAsync(int playerNumber, XboxLivePlayerInfo playerInfo)
        {
            SignInStatus signInStatus = SignInStatus.Success;

            TaskYieldInstruction <SignInResult> signInSilentlyTask = playerInfo.XboxLiveUser.SignInSilentlyAsync().AsCoroutine();

            yield return(signInSilentlyTask);

            try
            {
                signInStatus = signInSilentlyTask.Result.Status;
            }
            catch (Exception ex)
            {
                if (XboxLiveServicesSettings.Instance.DebugLogsOn)
                {
                    Debug.LogError("Exception occured: " + ex.Message);
                }
            }

            if (signInStatus != SignInStatus.Success)
            {
                TaskYieldInstruction <SignInResult> signInTask = playerInfo.XboxLiveUser.SignInAsync().AsCoroutine();
                yield return(signInTask);

                try
                {
                    signInStatus = signInTask.Result.Status;
                }
                catch (Exception ex)
                {
                    if (XboxLiveServicesSettings.Instance.DebugLogsOn)
                    {
                        Debug.LogError("Exception occured: " + ex.Message);
                    }
                }
            }

            try
            {
                // Throw any exceptions if needed.
                if (signInStatus == SignInStatus.Success)
                {
                    CurrentNumberOfPlayers++;
                    XboxLive.Instance.StatsManager.AddLocalUser(playerInfo.XboxLiveUser);
                    XboxLive.Instance.SocialManager.AddLocalUser(playerInfo.XboxLiveUser, SocialManagerExtraDetailLevel.PreferredColorLevel);
                    this.NotifyAllCallbacks(playerNumber, playerInfo.XboxLiveUser, XboxLiveAuthStatus.Succeeded, null, true);
                }
                else
                {
                    NotifyAllCallbacks(playerNumber, null, XboxLiveAuthStatus.Failed, "Sign In Failed: Player " + playerNumber + " failed. Sign In Status: " + signInStatus);
                }
            }
            catch (Exception ex)
            {
                if (XboxLiveServicesSettings.Instance.DebugLogsOn)
                {
                    Debug.LogError("Exception occured: " + ex.Message);
                }
            }
        }
        /// <summary>
        /// Adds and signs in a new Xbox Live User and assigns it a player number.
        /// Note: Different platforms support a different number of users.
        /// AddUser might fail if the player number is not within the range of supported users.
        /// </summary>
        /// <param name="playerNumber">The Player Number that should be assigned to the Xbox Live User</param>
        public IEnumerator SignInPlayer(int playerNumber)
        {
            yield return(null);

            if (ValidatePlayerNumber(playerNumber, "Add User", XboxLiveOperationType.SignIn))
            {
                if (!CurrentPlayers.ContainsKey(playerNumber))
                {
                    var newPlayerInfo = new XboxLivePlayerInfo()
                    {
                        SignInCallbacks  = new List <UnityAction <XboxLiveUser, XboxLiveAuthStatus, string> >(),
                        SignOutCallbacks = new List <UnityAction <XboxLiveUser, XboxLiveAuthStatus, string> >()
                    };
                    this.CurrentPlayers.Add(playerNumber, newPlayerInfo);
                }

#if ENABLE_WINMD_SUPPORT
                var playerInfo = this.CurrentPlayers[playerNumber];
                if (this.GetMaximumNumberOfPlayers() > 1)
                {
                    var autoPicker = new Windows.System.UserPicker {
                        AllowGuestAccounts = false
                    };
                    autoPicker.PickSingleUserAsync().AsTask().ContinueWith(
                        task =>
                    {
                        if (task.Status == TaskStatus.RanToCompletion)
                        {
                            playerInfo.WindowsUser         = task.Result;
                            playerInfo.XboxLiveUser        = new XboxLiveUser(playerInfo.WindowsUser);
                            XboxLiveUser.SignOutCompleted += XboxLiveUserSignOutCompleted;
                            this.PlayersPendingSignIn.Add(playerNumber);
                            this.StartCoroutine(this.SignInAsync(playerNumber, this.CurrentPlayers[playerNumber]));
                        }
                        else
                        {
                            if (XboxLiveServicesSettings.Instance.DebugLogsOn)
                            {
                                Debug.Log("Exception occured: " + task.Exception.Message);
                            }
                        }
                    });
                }
                else
                {
                    var usersTask = Windows.System.User.FindAllAsync().AsTask();
                    if (usersTask.Status == TaskStatus.RanToCompletion && usersTask.Result != null && usersTask.Result.Count > 0)
                    {
                        var windowsUser = usersTask.Result[0];
                        this.CurrentPlayers[playerNumber].WindowsUser  = windowsUser;
                        this.CurrentPlayers[playerNumber].XboxLiveUser = new XboxLiveUser(windowsUser);
                        this.StartCoroutine(this.SignInAsync(playerNumber, this.CurrentPlayers[playerNumber]));
                    }
                    else
                    {
                        this.CurrentPlayers[playerNumber].XboxLiveUser = new XboxLiveUser();
                        XboxLiveUser.SignOutCompleted += XboxLiveUserSignOutCompleted;
                        this.StartCoroutine(this.SignInAsync(playerNumber, this.CurrentPlayers[playerNumber]));
                    }
                }
#else
                this.CurrentPlayers[playerNumber].XboxLiveUser = new XboxLiveUser();
                XboxLiveUser.SignOutCompleted += XboxLiveUserSignOutCompleted;
                this.StartCoroutine(this.SignInAsync(playerNumber, this.CurrentPlayers[playerNumber]));
#endif
            }
        }
        /// <summary>
        /// Signs in a player. Attempts sign in silently first then sign in.
        /// </summary>
        /// <param name="playerNumber">The player number</param>
        /// <param name="playerInfo">The player info of the the player being signed in</param>
        /// <returns>A Coroutine</returns>
        private IEnumerator SignInAsync(int playerNumber, XboxLivePlayerInfo playerInfo)
        {
            SignInStatus signInStatus = SignInStatus.Success;

            TaskYieldInstruction <SignInResult> signInSilentlyTask = playerInfo.XboxLiveUser.SignInSilentlyAsync().AsCoroutine();

            yield return(signInSilentlyTask);

            try
            {
                signInStatus = signInSilentlyTask.Result.Status;
            }
            catch (Exception ex)
            {
                ExceptionManager.Instance.ThrowException(
                    ExceptionSource.SignInManager,
                    ExceptionType.SignInSilentlyFailed,
                    ex);
            }

            if (signInStatus != SignInStatus.Success)
            {
                TaskYieldInstruction <SignInResult> signInTask = playerInfo.XboxLiveUser.SignInAsync().AsCoroutine();
                yield return(signInTask);

                try
                {
                    signInStatus = signInTask.Result.Status;
                }
                catch (Exception ex)
                {
                    ExceptionManager.Instance.ThrowException(
                        ExceptionSource.SignInManager,
                        ExceptionType.SignInFailed,
                        ex);
                }
            }

            try
            {
                // Throw any exceptions if needed.
                if (signInStatus == SignInStatus.Success)
                {
                    CurrentNumberOfPlayers++;
                    XboxLive.Instance.StatsManager.AddLocalUser(playerInfo.XboxLiveUser);
                    XboxLive.Instance.SocialManager.AddLocalUser(playerInfo.XboxLiveUser, SocialManagerExtraDetailLevel.PreferredColorLevel);
                    this.NotifyAllCallbacks(playerNumber, playerInfo.XboxLiveUser, XboxLiveAuthStatus.Succeeded, null, true);
                }
                else
                {
                    this.CurrentPlayers[playerNumber].XboxLiveUser    = null;
                    this.CurrentPlayers[playerNumber].XboxLiveContext = null;
#if ENABLE_WINMD_SUPPORT
                    this.CurrentPlayers[playerNumber].WindowsUser = null;
#endif
                    NotifyAllCallbacks(playerNumber, null, XboxLiveAuthStatus.Failed, "Sign In Failed: Player " + playerNumber + " failed. Sign In Status: " + signInStatus);
                }
            }
            catch (Exception ex)
            {
                ExceptionManager.Instance.ThrowException(
                    ExceptionSource.SignInManager,
                    ExceptionType.SignInFailed,
                    ex);
            }
        }
        /// <summary>
        /// Adds and signs in a new Xbox Live User and assigns it a player number.
        /// Note: Different platforms support a different number of users.
        /// AddUser might fail if the player number is not within the range of supported users.
        /// </summary>
        /// <param name="playerNumber">The Player Number that should be assigned to the Xbox Live User</param>
        public IEnumerator SignInPlayer(int playerNumber)
        {
            yield return(null);

            if (ValidatePlayerNumber(playerNumber, "Add User", XboxLiveOperationType.SignIn))
            {
                if (!CurrentPlayers.ContainsKey(playerNumber))
                {
                    var newPlayerInfo = new XboxLivePlayerInfo()
                    {
                        SignInCallbacks  = new List <UnityAction <XboxLiveUser, XboxLiveAuthStatus, string> >(),
                        SignOutCallbacks = new List <UnityAction <XboxLiveUser, XboxLiveAuthStatus, string> >()
                    };
                    this.CurrentPlayers.Add(playerNumber, newPlayerInfo);
                }

#if ENABLE_WINMD_SUPPORT
                var playerInfo = this.CurrentPlayers[playerNumber];
                if (this.GetMaximumNumberOfPlayers() > 1)
                {
                    var autoPicker = new Windows.System.UserPicker {
                        AllowGuestAccounts = false
                    };
                    var userPicked = false;
                    autoPicker.PickSingleUserAsync().AsTask().ContinueWith(
                        task =>
                    {
                        if (task.Status == TaskStatus.RanToCompletion)
                        {
                            if (task.Result != null)
                            {
                                playerInfo.WindowsUser         = task.Result;
                                playerInfo.XboxLiveUser        = new XboxLiveUser(playerInfo.WindowsUser);
                                XboxLiveUser.SignOutCompleted += XboxLiveUserSignOutCompleted;
                                this.PlayersPendingSignIn.Add(playerNumber);
                                userPicked = true;
                            }
                            else
                            {
                                userPicked = false;
                                NotifyAllCallbacks(playerNumber, null, XboxLiveAuthStatus.Canceled, "Sign In Failed: Player " + playerNumber + " failed. Status: Canceled by the User.");
                            }
                        }
                        else
                        {
                            if (task.Status == TaskStatus.Canceled)
                            {
                                userPicked = false;
                                NotifyAllCallbacks(playerNumber, null, XboxLiveAuthStatus.Canceled, "Sign In Failed: Player " + playerNumber + " failed. Status: Canceled by the User.");
                            }
                            else
                            {
                                if (task.Status == TaskStatus.Faulted)
                                {
                                    ExceptionManager.Instance.ThrowException(
                                        ExceptionSource.SignInManager,
                                        ExceptionType.SignInFailed,
                                        task.Exception);
                                    userPicked = false;
                                    NotifyAllCallbacks(playerNumber, null, XboxLiveAuthStatus.Failed, "Sign In Failed: Player " + playerNumber + " failed.");
                                }
                            }
                        }
                    });
                    if (userPicked)
                    {
                        this.StartCoroutine(this.SignInAsync(playerNumber, this.CurrentPlayers[playerNumber]));
                    }
                }
                else
                {
                    var usersTask = Windows.System.User.FindAllAsync().AsTask();
                    if (usersTask.Status == TaskStatus.RanToCompletion && usersTask.Result != null && usersTask.Result.Count > 0)
                    {
                        var windowsUser = usersTask.Result[0];
                        this.CurrentPlayers[playerNumber].WindowsUser  = windowsUser;
                        this.CurrentPlayers[playerNumber].XboxLiveUser = new XboxLiveUser(windowsUser);
                        this.StartCoroutine(this.SignInAsync(playerNumber, this.CurrentPlayers[playerNumber]));
                    }
                    else
                    {
                        this.CurrentPlayers[playerNumber].XboxLiveUser = new XboxLiveUser();
                        XboxLiveUser.SignOutCompleted += XboxLiveUserSignOutCompleted;
                        this.StartCoroutine(this.SignInAsync(playerNumber, this.CurrentPlayers[playerNumber]));
                    }
                }
#else
                this.CurrentPlayers[playerNumber].XboxLiveUser = new XboxLiveUser();
                XboxLiveUser.SignOutCompleted += XboxLiveUserSignOutCompleted;
                this.StartCoroutine(this.SignInAsync(playerNumber, this.CurrentPlayers[playerNumber]));
#endif
            }
        }