/// <summary>
        /// Retries the login process after user consent to change session.
        /// </summary>
        /// <param name="request">The request to retry.</param>
        /// <param name="response">The response received from the server.</param>
        private async void RetryLogin(JsonObject request, JsonValue response)
        {
            // Ask the user consent to override session
            var consent = await App.DisplayAlert(
                Localization.ConfirmationDialogTitle,
                Localization.ConfirmationSesionChange,
                Localization.ButtonConfirm,
                Localization.Cancel);

            // If the user consent received
            if (consent)
            {
                // Modify the request based on server response
                var grantType = response.GetItemOrDefault("grant_type").GetStringValueOrDefault(string.Empty);
                if (!string.IsNullOrEmpty(grantType))
                {
                    request["grant_type"] = grantType;
                }

                var state = response.GetItemOrDefault("state").GetStringValueOrDefault(string.Empty);
                if (!string.IsNullOrEmpty(state))
                {
                    request["state"] = state;
                }

                // Resent the request to the server
                request.Add("override", true);
                WebHelper.SendAsync(
                    Uris.GetLoginUri(),
                    request.AsHttpContent(),
                    this.ProcessLoginResult,
                    () => this.IsBusy = false);
            }
            else
            {
                // Cancel the task
                this.UserName = string.Empty;
                this.Password = string.Empty;
                this.OnPropertyChanged(nameof(this.Password));
                this.IsBusy = false;
            }
        }
        /// <summary>
        /// Resumes the log in with the specified provider.
        /// </summary>
        /// <param name="authorizationUri">The user authorization URI.</param>
        private void ResumeLoginWith(Uri authorizationUri)
        {
            // Get the saved OAUTH state
            var stateString = Settings.Instance.GetValue(Settings.OauthToken, "{}");
            var oauthState  = (JsonObject)Json.Json.Read(stateString);

            Settings.Instance.Remove(Settings.OauthToken);

            // Get the query parameters from the URI
            Debug.WriteLine("ResumeLoginWith({0})", authorizationUri);
            var query = authorizationUri.Query;

            if ((query.Length > 0) && (query[0] == '?'))
            {
                query = query.Substring(1);
            }

            // Parse the keys and values
            var pairs     = query.Split('&');
            var arguments = new Dictionary <string, string>();

            foreach (var pair in pairs)
            {
                var split = pair.Split('=');
                arguments.Add(
                    Uri.UnescapeDataString(split[0]),
                    split.Length > 1 ? Uri.UnescapeDataString(split[1]) : string.Empty);
            }

            // If error is present
            if (arguments.ContainsKey("error"))
            {
                // Report error to the user
                App.DisplayAlert(
                    Localization.ErrorDialogTitle,
                    Localization.ErrorCancelled,
                    Localization.DialogDismiss);
                return;
            }

            // Add the result to the saved state
            foreach (var kvp in arguments)
            {
                oauthState.Add(kvp.Key, kvp.Value);
            }

            // Add the device and push token
            var deviceId  = ((App)Application.Current).DeviceId;
            var pushToken = ((App)Application.Current).PushToken;

            oauthState.Add("device", deviceId);
            if (!string.IsNullOrEmpty(pushToken))
            {
                oauthState.Add("push_token", pushToken);
            }

            // Setup error handlers
            // - If session is already opened by another device, request user consent
            var handlers = new Dictionary <System.Net.HttpStatusCode, Action <JsonValue> >
            {
                { System.Net.HttpStatusCode.Conflict, resp => this.RetryLogin(oauthState, resp) }
            };

            // Send request to the server
            this.IsBusy = true;
            WebHelper.SendAsync(
                Uris.GetLoginUri(),
                oauthState.AsHttpContent(),
                this.ProcessLoginResult,
                () => this.IsBusy = false,
                handlers);
        }
        /// <summary>
        /// Logs in the user with the provided credentials.
        /// </summary>
        private void Login()
        {
            // Login the user
            System.Diagnostics.Debug.WriteLine("{0}:{1}", this.UserName, this.Password);

            // If already logging in
            if (this.IsBusy)
            {
                return;
            }

            // Validate that the user name is a valid email
            var user    = this.UserName.Trim().ToLower();
            var isEmail = Regex.IsMatch(
                user,
                @"\A(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\Z",
                RegexOptions.IgnoreCase);

            if (!isEmail)
            {
                App.DisplayAlert(
                    Localization.ErrorDialogTitle,
                    Localization.ErrorInvalidUserLogin,
                    Localization.DialogDismiss);
                return;
            }

            // Validate that the password is present
            if (this.Password.Length <= 2)
            {
                App.DisplayAlert(
                    Localization.ErrorDialogTitle,
                    Localization.ErrorInvalidPassword,
                    Localization.DialogDismiss);
                return;
            }

            // Prepare the data to be send to the server
            var deviceId = ((App)Application.Current).DeviceId;
            var request  = new Json.JsonObject
            {
                { "grant_type", "password" },
                { "username", user },
                { "password", this.Password },
                { "scope", "user submit-report" },
                { "device", deviceId }
            };

            // If push token exists
            var pushToken = ((App)Application.Current).PushToken;

            if (!string.IsNullOrEmpty(pushToken))
            {
                request.Add("push_token", pushToken);
            }

            // Setup error handlers
            // - If session is already opened by another device, request user consent
            var handlers = new Dictionary <System.Net.HttpStatusCode, Action <JsonValue> >
            {
                { System.Net.HttpStatusCode.Conflict, resp => this.RetryLogin(request, resp) }
            };

            // Send request to the server
            this.IsBusy = true;
            WebHelper.SendAsync(
                Uris.GetLoginUri(),
                request.AsHttpContent(),
                this.ProcessLoginResult,
                () => this.IsBusy = false,
                handlers);
        }