/// <summary>
 /// List all objects along with versions non-recursively in a bucket with a given prefix, optionally emulating a directory
 /// </summary>
 /// <param name="args">ListObjectsArgs Arguments Object with information like Bucket name, prefix, recursive listing, versioning</param>
 /// <param name="cancellationToken">Optional cancellation token to cancel the operation</param>
 /// <returns>An observable of items that client can subscribe to</returns>
 public IObservable <VersionItem> ListObjectVersionsAsync(ListObjectsArgs args, CancellationToken cancellationToken = default(CancellationToken))
 {
     return(Observable.Create <VersionItem>(
                async(obs, ct) =>
     {
         bool isRunning = true;
         var delimiter = (args.Recursive) ? string.Empty : "/";
         string marker = string.Empty;
         using (var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, ct))
         {
             while (isRunning)
             {
                 GetObjectListArgs goArgs = new GetObjectListArgs()
                                            .WithBucket(args.BucketName)
                                            .WithPrefix(args.Prefix)
                                            .WithDelimiter(delimiter)
                                            .WithVersions(args.Versions)
                                            .WithMarker(marker);
                 Tuple <ListVersionsResult, List <VersionItem> > objectList = await this.GetObjectVersionsListAsync(goArgs, cts.Token).ConfigureAwait(false);
                 ListObjectVersionResponse listObjectsItemResponse = new ListObjectVersionResponse(args, objectList, obs);
                 marker = listObjectsItemResponse.NextMarker;
                 isRunning = objectList.Item1.IsTruncated;
                 cts.Token.ThrowIfCancellationRequested();
             }
         }
     }));
 }
        /// <summary>
        /// List all objects non-recursively in a bucket with a given prefix, optionally emulating a directory
        /// </summary>
        /// <param name="bucketName">Bucket to list objects from</param>
        /// <param name="prefix">Filters all objects beginning with a given prefix</param>
        /// <param name="recursive">Set to true to recursively list all objects</param>
        /// <param name="cancellationToken">Optional cancellation token to cancel the operation</param>
        /// <returns>An observable of items that client can subscribe to</returns>
        public IObservable <Item> ListObjectsAsync(string bucketName, string prefix = null, bool recursive = false, CancellationToken cancellationToken = default(CancellationToken))
        {
            ListObjectsArgs args = new ListObjectsArgs()
                                   .WithBucket(bucketName)
                                   .WithPrefix(prefix)
                                   .WithRecursive(recursive);

            return(this.ListObjectsAsync(args, cancellationToken));
        }
        internal ListObjectVersionResponse(ListObjectsArgs args, Tuple <ListVersionsResult, List <Item> > objectList, IObserver <Item> obs)
        {
            this.ItemObservable = obs;
            string marker = string.Empty;

            foreach (Item item in objectList.Item2)
            {
                this.BucketObjectsLastItem = item;
                if (objectList.Item1.EncodingType == "url")
                {
                    item.Key = HttpUtility.UrlDecode(item.Key);
                }
                this.ItemObservable.OnNext(item);
            }
            if (objectList.Item1.NextMarker != null)
            {
                if (objectList.Item1.EncodingType == "url")
                {
                    NextMarker    = HttpUtility.UrlDecode(objectList.Item1.NextMarker);
                    NextKeyMarker = HttpUtility.UrlDecode(objectList.Item1.NextKeyMarker);
                    NextVerMarker = HttpUtility.UrlDecode(objectList.Item1.NextVersionIdMarker);
                }
                else
                {
                    NextMarker    = objectList.Item1.NextMarker;
                    NextKeyMarker = objectList.Item1.NextKeyMarker;
                    NextVerMarker = objectList.Item1.NextVersionIdMarker;
                }
            }
            else if (this.BucketObjectsLastItem != null)
            {
                if (objectList.Item1.EncodingType == "url")
                {
                    NextMarker    = HttpUtility.UrlDecode(this.BucketObjectsLastItem.Key);
                    NextKeyMarker = HttpUtility.UrlDecode(this.BucketObjectsLastItem.Key);
                    NextVerMarker = HttpUtility.UrlDecode(this.BucketObjectsLastItem.VersionId);
                }
                else
                {
                    NextMarker    = this.BucketObjectsLastItem.Key;
                    NextKeyMarker = this.BucketObjectsLastItem.Key;
                    NextVerMarker = this.BucketObjectsLastItem.VersionId;
                }
            }
        }