/// <summary>
        /// Submit the download request and then use the BulkDownloadOperation result to
        /// track status until the download is complete using GetStatusAsync.
        /// </summary>
        /// <param name="submitDownloadParameters"></param>
        /// <returns></returns>
        private async Task SubmitPollDownloadAsync(
            SubmitDownloadParameters submitDownloadParameters)
        {
            var bulkDownloadOperation = await BulkServiceManager.SubmitDownloadAsync(submitDownloadParameters);

            BulkOperationStatus <DownloadStatus> downloadStatus;
            var waitTime = new TimeSpan(0, 0, 5);

            for (int i = 0; i < 24; i++)
            {
                Thread.Sleep(waitTime);

                downloadStatus = await bulkDownloadOperation.GetStatusAsync();

                if (downloadStatus.Status == DownloadStatus.Completed)
                {
                    break;
                }
            }

            var resultFilePath = await bulkDownloadOperation.DownloadResultFileAsync(
                localResultDirectoryName : FileDirectory,
                localResultFileName : ResultFileName,
                decompress : true,
                overwrite : true // Set this value true if you want to overwrite the same file.
                );

            OutputStatusMessage(string.Format("Download result file: {0}", resultFilePath));
        }
        /// <summary>
        /// Submit the download request and then use the BulkDownloadOperation result to
        /// track status until the download is complete using TrackAsync.
        /// </summary>
        /// <param name="submitDownloadParameters"></param>
        /// <returns></returns>
        private async Task SubmitTrackDownloadAsync(
            SubmitDownloadParameters submitDownloadParameters,
            Progress <BulkOperationProgressInfo> progress,
            CancellationToken cancellationToken)
        {
            var bulkDownloadOperation = await BulkServiceManager.SubmitDownloadAsync(submitDownloadParameters);

            BulkOperationStatus <DownloadStatus> downloadStatus = await bulkDownloadOperation.TrackAsync(
                progress : progress,
                cancellationToken : cancellationToken);

            var resultFilePath = await bulkDownloadOperation.DownloadResultFileAsync(
                localResultDirectoryName : FileDirectory,
                localResultFileName : ResultFileName,
                decompress : true,
                overwrite : true // Set this value true if you want to overwrite the same file.
                );

            OutputStatusMessage(string.Format("Download result file: {0}", resultFilePath));
        }
        /// <summary>
        /// Submit the download request and then use the BulkDownloadOperation result to
        /// track status until the download is complete e.g. either using
        /// TrackAsync or GetStatusAsync.
        /// </summary>
        /// <param name="submitDownloadParameters"></param>
        /// <returns></returns>
        private async Task SubmitAndDownloadAsync(SubmitDownloadParameters submitDownloadParameters)
        {
            var bulkDownloadOperation = await BulkServiceManager.SubmitDownloadAsync(submitDownloadParameters);

            // You may optionally cancel the TrackAsync operation after a specified time interval.
            var tokenSource = new CancellationTokenSource();

            tokenSource.CancelAfter(TimeoutInMilliseconds);

            BulkOperationStatus <DownloadStatus> downloadStatus = await bulkDownloadOperation.TrackAsync(null, tokenSource.Token);

            // You can use TrackAsync to poll until complete as shown above,
            // or use custom polling logic with GetStatusAsync as shown below.

            //BulkOperationStatus<DownloadStatus> downloadStatus;
            //var waitTime = new TimeSpan(0, 0, 5);

            //for (int i = 0; i < 24; i++)
            //{
            //    Thread.Sleep(waitTime);

            //    downloadStatus = await bulkDownloadOperation.GetStatusAsync();

            //    if (downloadStatus.Status == DownloadStatus.Completed)
            //    {
            //        break;
            //    }
            //}

            var resultFilePath = await bulkDownloadOperation.DownloadResultFileAsync(
                FileDirectory,
                ResultFileName,
                decompress : true,
                overwrite : true // Set this value true if you want to overwrite the same file.
                );

            OutputStatusMessage(string.Format("Download result file: {0}\n", resultFilePath));
        }
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                BulkServiceManager = new BulkServiceManager(
                    authorizationData: authorizationData,
                    apiEnvironment: environment);
                BulkServiceManager.StatusPollIntervalInMilliseconds = 5000;

                // Track download or upload progress

                var progress = new Progress <BulkOperationProgressInfo>(x =>
                                                                        OutputStatusMessage(string.Format("{0} % Complete",
                                                                                                          x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                // Some BulkServiceManager operations can be cancelled after a time interval.

                var tokenSource = new CancellationTokenSource();
                tokenSource.CancelAfter(TimeoutInMilliseconds);

                // Download all campaigns, ad groups, and ads in the account.

                var entities = new[] {
                    DownloadEntity.Campaigns,
                    DownloadEntity.AdGroups,
                    DownloadEntity.Ads,
                };

                // DownloadParameters is used for Option A below.
                var downloadParameters = new DownloadParameters
                {
                    CampaignIds         = null,
                    DataScope           = DataScope.EntityData | DataScope.QualityScoreData,
                    DownloadEntities    = entities,
                    FileType            = FileType,
                    LastSyncTimeInUTC   = null,
                    ResultFileDirectory = FileDirectory,
                    ResultFileName      = DownloadFileName,
                    OverwriteResultFile = true
                };

                // SubmitDownloadParameters is used for Option B and Option C below.
                var submitDownloadParameters = new SubmitDownloadParameters
                {
                    CampaignIds       = null,
                    DataScope         = DataScope.EntityData | DataScope.QualityScoreData,
                    DownloadEntities  = entities,
                    FileType          = FileType,
                    LastSyncTimeInUTC = null
                };

                // Option A - Background Completion with BulkServiceManager
                // You can submit a download or upload request and the BulkServiceManager will automatically
                // return results. The BulkServiceManager abstracts the details of checking for result file
                // completion, and you don't have to write any code for results polling.

                OutputStatusMessage("-----\nAwaiting Background Completion with DownloadFileAsync...");
                await BackgroundCompletionAsync(
                    downloadParameters : downloadParameters,
                    progress : progress,
                    cancellationToken : tokenSource.Token);

                // Alternatively we can use DownloadEntitiesAsync if we want to work with the entities in memory.
                // If you enable this option the result file from BackgroundCompletionAsync will also be deleted
                // if written to the same working directory.
                OutputStatusMessage("-----\nAwaiting Background Completion with DownloadEntitiesAsync...");
                var downloadEntities = await DownloadEntitiesAsync(
                    downloadParameters : downloadParameters,
                    progress : progress,
                    cancellationToken : tokenSource.Token);

                // Option B - Submit and Download with BulkServiceManager
                // Submit the download request and then use the BulkDownloadOperation result to
                // track status until the download is complete e.g. either using
                // TrackAsync or GetStatusAsync.

                OutputStatusMessage("-----\nAwaiting Submit, Track, and Download...");
                await SubmitTrackDownloadAsync(
                    submitDownloadParameters : submitDownloadParameters,
                    progress : progress,
                    cancellationToken : tokenSource.Token);

                // A second variation of Option B.
                // See SubmitTrackDownloadAsync for details.

                OutputStatusMessage("-----\nAwaiting Submit, Poll, and Download...");
                await SubmitTrackDownloadAsync(
                    submitDownloadParameters : submitDownloadParameters,
                    progress : progress,
                    cancellationToken : tokenSource.Token);

                // Option C - Download Results with BulkServiceManager
                // If for any reason you have to resume from a previous application state,
                // you can use an existing download request identifier and use it
                // to download the result file.

                // For example you might have previously retrieved a request ID using SubmitDownloadAsync.

                var bulkDownloadOperation = await BulkServiceManager.SubmitDownloadAsync(
                    parameters : submitDownloadParameters);

                var requestId = bulkDownloadOperation.RequestId;

                // Given the request ID above, you can resume the workflow and download the bulk file.
                // The download request identifier is valid for two days.
                // If you do not download the bulk file within two days, you must request it again.

                OutputStatusMessage("-----\nAwaiting Download Results...");
                await DownloadResultsAsync(
                    requestId : requestId,
                    authorizationData : authorizationData,
                    progress : progress,
                    cancellationToken : tokenSource.Token);
            }
            // Catch authentication exceptions
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V12.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(String.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V12.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(String.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(String.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
        }