/// <summary>
        /// Because the app has registered to support "Photos" extension the agent will be invoked
        /// and requested to download each image binary on a per need basis (e.g.: the user
        /// has tapped on the photo). We only receive this operation for the albums that require
        /// authentication (i.e. : we have explicitly set the property RequiresAuthentication = true)
        /// </summary>
        /// <param name="operation">The operation that we need to perform</param>
        private async Task ProcessOperation(DownloadImageOperation operation)
        {
            Logger.Log("Agent", "DownloadImageOperation(" + operation.PhotoId + ", " + operation.DesiredImageType + ")");

            try
            {
                OnlinePicture image = await manager.GetPictureByRemoteIdAsync(operation.PhotoId);

                // Download according to the desired image type

                if (operation.DesiredImageType == ImageType.SmallThumbnail)
                {
                    await image.SetThumbnailSmallAsync(await Helpers.MakeStreamFromUrl(image.ThumbnailSmallUrl));
                }
                else if (operation.DesiredImageType == ImageType.LargeThumbnail)
                {
                    await image.SetThumbnailLargeAsync(await Helpers.MakeStreamFromUrl(image.ThumbnailLargeUrl));
                }
                else if (operation.DesiredImageType == ImageType.FullSize)
                {
                    await image.SetContentAsync(await Helpers.MakeStreamFromUrl(image.ContentUrl));
                }

                await manager.SaveMediaItemAsync(image);
            }
            catch (Exception e)
            {
                Helpers.HandleException(e);
            }
            finally
            {
                operation.SafeNotifyCompletion();
            }
        }
        /// <summary>
        /// Because the app has registered to support "Photos" extension the agent will be invoked
        /// and requested to download the album items when the user taps on our tile
        /// in the photos hub. This method handles the operation by synchronizing the local
        /// store with our web server (Bing Images).
        /// </summary>
        /// <param name="operation">The operation that we need to perform</param>
        private async Task ProcessOperation(DownloadAlbumItemsOperation operation)
        {
            try
            {
                Logger.Log("Agent", "DownloadAlbumItemsOperation(" + operation.ParentAlbumId + ")");

                if (string.IsNullOrEmpty(operation.ParentAlbumId))
                {
                    // An empty ParentAlbumId means that we need to populate the root album
                    OnlinePictureAlbum rootAlbum = await manager.GetRootPictureAlbumAsync();

                    // Let's add the top level albums
                    // Simulate server request to get the top level albums
                    // (note: this code sample builds the list statically)
                    List <BingApi.Album> topLevelAlbums = BingApi.GetAlbums();
                    foreach (BingApi.Album newAlbum in topLevelAlbums)
                    {
                        OnlinePictureAlbum album = await manager.GetPictureAlbumByRemoteIdAsync(newAlbum.id);

                        if (null == album)
                        {
                            album       = manager.CreatePictureAlbum(newAlbum.id, rootAlbum.Id);
                            album.Title = newAlbum.title;

                            // The albums that have the RequiresAuthentication flag set will
                            // trigger a DownloadImageOperation every time the Photos app needs
                            // to display an image that hasn't already been downloaded.
                            album.RequiresAuthentication = newAlbum.authRequired;

                            await manager.SavePictureAlbumAsync(album);
                        }
                    }
                }
                else
                {
                    // ParentAlbumId is the remote id of the album that we need to populate
                    OnlinePictureAlbum album = await manager.GetPictureAlbumByRemoteIdAsync(operation.ParentAlbumId);

                    // Make a network call to get the most recent VersionStamp
                    string newVersionStamp = await BingApi.GetVersionStampAsync(operation.ParentAlbumId);

                    // Is up to the app to use the VersionStamp on the album to best suit its needs.
                    // The OS doesn't use this value. The app can use it to determine if the album is
                    // up to date. Only trigger a full sync if the album is not up to date.
                    if (album.VersionStamp != newVersionStamp)
                    {
                        // Get all the pictures that are currently in the album
                        OnlineMediaItemQueryResult query       = album.GetContentsQuery();
                        IList <IOnlineMediaItem>   oldPictures = await query.GetItemsAsync();

                        // Mark all current pictures for deletion
                        Dictionary <string, OnlinePicture> photosToDelete = new Dictionary <string, OnlinePicture>();
                        foreach (IOnlineMediaItem item in oldPictures)
                        {
                            OnlinePicture onlinePicture = item as OnlinePicture;
                            if (null != onlinePicture)
                            {
                                photosToDelete.Add(onlinePicture.RemoteId, onlinePicture);
                            }
                        }

                        // Contact server to download the metadata for all the items in the album
                        List <BingApi.Photo> newPhotos = await BingApi.GetAllPhotosMetadataAsync(operation.ParentAlbumId);

                        // Fill with new photos
                        List <OnlinePicture> photosToSave = new List <OnlinePicture>();
                        // Save a reference to the most recent photo among the new photos to use it as the cover for the album
                        OnlinePicture mostRecent = null;
                        foreach (BingApi.Photo newPhoto in newPhotos)
                        {
                            OnlinePicture onlinePicture = await manager.GetPictureByRemoteIdAsync(newPhoto.id);

                            if (null == onlinePicture)
                            {
                                OnlinePicture localPhoto = manager.CreatePicture(newPhoto.id, album.Id);
                                localPhoto.Title             = newPhoto.title;
                                localPhoto.CreationTime      = newPhoto.timestamp;
                                localPhoto.ThumbnailSmallUrl = new Uri(newPhoto.smallThumbnailUrl); // required
                                localPhoto.ThumbnailLargeUrl = new Uri(newPhoto.largeThumbnailUrl); // required
                                //localPhoto.ContentUrl = new Uri(newPhoto.fullSizeUrl); // optional
                                photosToSave.Add(localPhoto);

                                // Check if the current photo is the most recent one
                                if (null == mostRecent || (localPhoto.CreationTime > mostRecent.CreationTime))
                                {
                                    mostRecent = localPhoto;
                                }

                                if (photosToSave.Count > 500)
                                {
                                    // Save the photos in one bulk transaction, note the transaction can't be larger than 1000,
                                    // but we break it into 500 for good measure
                                    await manager.SaveMediaItemsAsync(photosToSave);

                                    photosToSave.Clear();
                                }
                            }
                            else
                            {
                                // The photo is still on the server. Keep it.
                                photosToDelete.Remove(newPhoto.id);
                            }
                        }

                        // Most server APIs will provide a distinct cover image
                        // Here we use the most recent photo update the cover image
                        if (null != mostRecent &&
                            album.CoverImageUrl != mostRecent.ThumbnailSmallUrl)
                        {
                            await album.SetCoverImageAsync(null);

                            album.CoverImageUrl = mostRecent.ThumbnailSmallUrl;
                        }

                        // Update last modified time
                        album.VersionStamp = newVersionStamp;

                        // Calling SavePictureAlbumAsync will flicker the entire album page.
                        // It can produce a poor user experience if called everytime
                        // we receive a newDownloadAlbumItemsOperation.
                        // For that reason, we only call this when the album has been updated.
                        // So, we always check if the VersionStamp has been updated.
                        await manager.SavePictureAlbumAsync(album);

                        // Save all the photos in one bulk transaction:
                        if (photosToSave.Count > 0)
                        {
                            await manager.SaveMediaItemsAsync(photosToSave);
                        }

                        // Purge old photos
                        if (null != photosToDelete)
                        {
                            foreach (OnlinePicture photo in photosToDelete.Values)
                            {
                                await manager.DeleteMediaItemAsync(photo);
                            }
                        }
                    }
                }
                Logger.Log("Agent", "Precessing DownloadAlbumItemsOperation for Id=" + operation.ParentAlbumId);
            }
            catch (Exception e)
            {
                Helpers.HandleException(e);
            }
            finally
            {
                operation.SafeNotifyCompletion();
            }
        }