A simple class that represents the result of an operation.
        /// <summary>
        /// Waits for the operation to complete.
        /// </summary>
        /// <param name="operationResult">The operation result.</param>
        internal string WaitOnOperation(OperationResult operationResult)
        {
            // TODO: Re-factor this mess.
            this.ProgressTrackerObject.UpdateProgress("Starting", 0);

            var trackingResult = this.HandleOperationResponse(operationResult, this.IsResourceCreateOrUpdate ? operationResult.OperationUri : operationResult.LocationUri);

            while (trackingResult != null && trackingResult.ShouldWait)
            {
                operationResult =
                    this.GetResourcesClient()
                        .GetOperationResult<JToken>(trackingResult.TrackingUri, this.CancellationToken)
                        .Result;

                trackingResult = this.HandleOperationResponse(operationResult, trackingResult.TrackingUri);

                if (trackingResult.ShouldWait && trackingResult.RetryAfter != null)
                {
                    Task.Delay(delay: trackingResult.RetryAfter.Value, cancellationToken: this.CancellationToken).Wait(cancellationToken: this.CancellationToken);
                }
            }

            this.ProgressTrackerObject.UpdateProgress("Complete", 100);

            return operationResult.Value;
        }
            /// <summary>
            /// Gets the azure async operation state.
            /// </summary>
            /// <param name="operationResult">The operation result.</param>
            private string GetAzureAsyncOperationState(OperationResult operationResult)
            {
                try
                {
                    var result = this.ResourcesClientFactory()
                        .GetAzureAsyncOperationResource(operationResult.AzureAsyncOperationUri, this.CancellationToken)
                        .Result;

                    return result == null
                        ? null
                        : result.Status;
                }
                catch (Exception e)
                {
                    if (e.IsFatal())
                    {
                        throw;
                    }

                    return null;
                }
            }
            /// <summary>
            /// Gets the state from the resource.
            /// </summary>
            /// <param name="operationResult">The operation result.</param>
            private static string GetResourceState(OperationResult operationResult)
            {
                Resource<InsensitiveDictionary<JToken>> resource;
                if (!operationResult.Value.TryConvertTo<Resource<InsensitiveDictionary<JToken>>>(out resource))
                {
                    return null;
                }

                if (resource == null)
                {
                    return null;
                }

                resource.Properties = resource.Properties ?? new InsensitiveDictionary<JToken>();
                JToken provisioningStateJToken;

                return resource.Properties.TryGetValue("provisioningState", out provisioningStateJToken)
                    ? provisioningStateJToken.ToString()
                    : null;
            }
        /// <summary>
        /// Indicates a failed terminal state.
        /// </summary>
        /// <param name="operationResult">The result of the operation.</param>
        /// <param name="message">The exception message.</param>
        private void FailedResult(OperationResult operationResult, string message)
        {
            var result = new TrackingOperationResult
            {
                ShouldWait = false,
                Failed = true,
                RetryAfter = operationResult.RetryAfter ?? LongRunningOperationHelper.DefaultRetryAfter,
                TrackingUri = operationResult.LocationUri ?? operationResult.OperationUri,
                OperationResult = operationResult,
            };

            this.UpdateProgress(result);

            throw new InvalidOperationException(message);
        }
 /// <summary>
 /// Extra code for handling resource create/update calls.
 /// </summary>
 /// <param name="operationResult">The result of the operation.</param>
 private string GetOperationState(OperationResult operationResult)
 {
     return operationResult.AzureAsyncOperationUri != null
         ? this.GetAzureAsyncOperationState(operationResult)
         : ProgressTracker.GetResourceState(operationResult);
 }
        /// <summary>
        /// Indicates an in-progress state.
        /// </summary>
        /// <param name="operationResult">The result of the operation.</param>
        private TrackingOperationResult WaitResult(OperationResult operationResult)
        {
            var result = new TrackingOperationResult
            {
                ShouldWait = true,
                Failed = false,
                RetryAfter = operationResult.RetryAfter ?? LongRunningOperationHelper.DefaultRetryAfter,
                TrackingUri = operationResult.LocationUri ?? operationResult.OperationUri,
                OperationResult = operationResult,
            };

            this.UpdateProgress(result);
            return result;
        }
        /// <summary>
        /// Extra code for handling resource create/update calls.
        /// </summary>
        /// <param name="operationResult">The result of the operation.</param>
        private TrackingOperationResult HandleCreateOrUpdateResponse(OperationResult operationResult)
        {
            Resource<InsensitiveDictionary<JToken>> resource;
            if (!operationResult.Value.TryConvertTo<Resource<InsensitiveDictionary<JToken>>>(out resource))
            {
                return null;
            }

            if (resource == null && operationResult.HttpStatusCode == HttpStatusCode.Created)
            {
                return this.SuccessfulResult(operationResult);
            }

            if (resource == null)
            {
                this.FailedResult(
                    operationResult,
                    "The operation failed because resource could not be de-serialized.");
            }

            resource.Properties = resource.Properties ?? new InsensitiveDictionary<JToken>();

            JToken provisioningStateJToken;
            if (resource.Properties.TryGetValue("provisioningState", out provisioningStateJToken))
            {
                TerminalProvisioningStates resourceProvisioningState;
                if (Enum.TryParse(value: provisioningStateJToken.ToString(), ignoreCase: true, result: out resourceProvisioningState))
                {
                    if (resourceProvisioningState == TerminalProvisioningStates.Succeeded ||
                        resourceProvisioningState == TerminalProvisioningStates.Ready)
                    {
                        return this.SuccessfulResult(operationResult);
                    }

                    if (resourceProvisioningState == TerminalProvisioningStates.Failed ||
                        resourceProvisioningState == TerminalProvisioningStates.Canceled)
                    {
                        this.FailedResult(
                            operationResult,
                            string.Format("The operation failed because resource is in the: '{0}' state. Please check the logs for more details.", provisioningStateJToken));
                    }
                }
                else
                {
                    return this.WaitResult(operationResult);
                }
            }

            return this.SuccessfulResult(operationResult);
        }
        /// <summary>
        /// Handles the operation response/
        /// </summary>
        /// <param name="operationResult">The result of the operation.</param>
        /// <param name="lastRequestUri">The last <see cref="Uri"/> that was used to request operation state.</param>
        private TrackingOperationResult HandleOperationResponse(OperationResult operationResult, Uri lastRequestUri)
        {
            if (!operationResult.HttpStatusCode.IsSuccessfulRequest())
            {
                if (operationResult.HttpStatusCode.IsServerFailureRequest() ||
                    operationResult.HttpStatusCode == HttpStatusCodeExt.TooManyRequests)
                {
                    var result = new TrackingOperationResult
                    {
                        ShouldWait = true,
                        Failed = false,
                        RetryAfter = operationResult.RetryAfter ?? LongRunningOperationHelper.DefaultRetryAfter,
                        TrackingUri = lastRequestUri,
                        OperationResult = operationResult,
                    };

                    this.UpdateProgress(result);
                    return result;
                }
                else
                {
                    this.FailedResult(
                        operationResult,
                        string.Format("The operation failed because the resource provider returned an unexpected HTTP status code of: '{0}'.", (int)operationResult.HttpStatusCode));
                }
            }

            if (operationResult.HttpStatusCode == HttpStatusCode.Accepted)
            {
                return this.WaitResult(operationResult);
            }

            if (operationResult.HttpStatusCode != HttpStatusCode.OK &&
                operationResult.HttpStatusCode != HttpStatusCode.Created &&
                (!this.IsResourceCreateOrUpdate && operationResult.HttpStatusCode != HttpStatusCode.NoContent))
            {
                this.FailedResult(
                    operationResult,
                    string.Format("The operation failed because the resource provider returned an unexpected HTTP status code of: '{0}'.", (int)operationResult.HttpStatusCode));
            }

            return this.IsResourceCreateOrUpdate
                ? this.HandleCreateOrUpdateResponse(operationResult)
                : this.SuccessfulResult(operationResult);

        }
            /// <summary>
            /// Gets the state from the resource.
            /// </summary>
            /// <param name="operationResult">The operation result.</param>
            private static string GetResourceState(OperationResult operationResult)
            {
                var resource = operationResult.Value == null
                    ? null
                    : operationResult.Value
                        .ToObject<Resource<InsensitiveDictionary<JToken>>>(JsonExtensions.JsonObjectTypeSerializer);

                if (resource == null)
                {
                    return null;
                }

                resource.Properties = resource.Properties ?? new InsensitiveDictionary<JToken>();
                JToken provisioningStateJToken;

                return resource.Properties.TryGetValue("provisioningState", out provisioningStateJToken)
                    ? provisioningStateJToken.ToString()
                    : null;
            }
 /// <summary>
 /// Extra code for handling resource create/update calls.
 /// </summary>
 /// <param name="operationResult">The result of the operation.</param>
 private string GetOperationState(OperationResult operationResult)
 {
     return(operationResult.AzureAsyncOperationUri != null
         ? this.GetAzureAsyncOperationState(operationResult)
         : ProgressTracker.GetResourceState(operationResult));
 }