private void UpdateProgress()
        {
            try
            {
                long total = 0, done = 0;
                int  length = this.ProgressInfoList.Count;

                for (int i = 0; i < length; i++)
                {
                    ProgressInfo p = this.ProgressInfoList.Values.ElementAt(i);
                    total += p.Total;
                    done  += p.Transferred;
                }

                if (total == 0)
                {
                    return;
                }

                int            percentComplete = (int)(done * 100 / total);
                ProgressRecord progress        = new ProgressRecord(1,
                                                                    string.Format("Copying '{0}'", this.folderName),
                                                                    string.Format("{0}% of {1}", percentComplete, GetSize(total)));

                progress.PercentComplete = percentComplete;
                //progress.CurrentOperation = "Downloading files";
                //progress.StatusDescription = done + "/" + total;

                //progress.StatusDescription = string.Format("{0}% of {1}", percentComplete, GetSize(total));

                this.CmdLetObj.WriteProgress(progress);
            }
            catch { }
        }
        void IAction.CopyFileItem(ProgressInfo progressInfo)
        {
            string fileName        = System.IO.Path.Combine(target.FullName, child.FileName);
            bool   duplicateFile   = File.Exists(fileName);
            bool   hashcodeMatches = duplicateFile ? Utility.GetMD5HashFromFile(fileName).Equals(child.Hash) : false;

            if (duplicateFile && actionType == ActionType.None)
            {
                throw new IOException("File already exist");
            }
            else if (!duplicateFile || actionType == ActionType.Force || (actionType == ActionType.Sync && !hashcodeMatches))
            {
                using (var fileStream = new FileStream(fileName, actionType == ActionType.Force || actionType == ActionType.Sync ? FileMode.Create : FileMode.CreateNew))
                {
                    var downloader = client.GetAsyncFileDownloader(child);

                    progressInfo.ProgressTotal(progressInfo.FileIndex, child.FileSizeBytes.GetValueOrDefault());

                    downloader.OnTransferProgress =
                        (sender, args) =>
                    {
                        if (args.Progress.TotalBytes > 0)
                        {
                            progressInfo.ProgressTransferred(progressInfo.FileIndex, args.Progress.BytesTransferred);
                        }
                    };

                    downloader.DownloadToAsync(fileStream).Wait();

                    fileStream.Close();
                    fileSupportDelegate(fileName);
                }
            }
        }
        void IAction.CopyFileItem(ProgressInfo progressInfo)
        {
            string fileName = System.IO.Path.Combine(target.FullName, child.FileName);
            bool duplicateFile = File.Exists(fileName);
            bool hashcodeMatches = duplicateFile ? Utility.GetMD5HashFromFile(fileName).Equals(child.Hash) : false;

            if (duplicateFile && actionType == ActionType.None)
            {
                throw new IOException("File already exist");
            }
            else if (!duplicateFile || actionType == ActionType.Force || (actionType == ActionType.Sync && !hashcodeMatches))
            {
                using (var fileStream = new FileStream(fileName, actionType == ActionType.Force || actionType == ActionType.Sync ? FileMode.Create : FileMode.CreateNew))
                {
                    var downloader = client.GetAsyncFileDownloader(child);

                    progressInfo.ProgressTotal(progressInfo.FileIndex, child.FileSizeBytes.GetValueOrDefault());

                    downloader.OnTransferProgress =
                        (sender, args) =>
                        {
                            if (args.Progress.TotalBytes > 0)
                            {
                                progressInfo.ProgressTransferred(progressInfo.FileIndex, args.Progress.BytesTransferred);
                            }
                        };

                    downloader.DownloadToAsync(fileStream).Wait();
                    
                    fileStream.Close();
                    fileSupportDelegate(fileName);
                }
            }
        }
        void IAction.CopyFileItem(ProgressInfo progressInfo)
        {
            var fileInfo = (FileInfo)child;

            Models.Item fileItem = null;
            fileName = child.Name;
            try
            {
                fileItem = client.Items.ByPath(uploadTarget.url, "/" + child.Name).Execute();
            }
            catch (ODataException e) {
                if (e.Code != System.Net.HttpStatusCode.NotFound)
                {
                    throw e;
                }
            }

            bool duplicate       = fileItem != null && fileItem is Models.File;
            bool hashcodeMatches = duplicate ? (fileItem as Models.File).Hash.Equals(Utility.GetMD5HashFromFile(child.FullName)) : false;

            if (duplicate && actionType == ActionType.None)
            {
                throw new IOException("File already exist");
            }
            else if (!duplicate || actionType == ActionType.Force || (actionType == ActionType.Sync && !hashcodeMatches))
            {
                var uploadSpec = new UploadSpecificationRequest
                {
                    CanResume   = false,
                    Details     = details,
                    FileName    = fileInfo.Name,
                    FileSize    = fileInfo.Length,
                    Method      = UploadMethod.Threaded,
                    Parent      = uploadTarget.url,
                    ThreadCount = 4,
                    Raw         = true
                };

                using (var platformFileInfo = new PlatformFileInfo(fileInfo))
                {
                    var uploader = client.GetAsyncFileUploader(uploadSpec, platformFileInfo);

                    progressInfo.ProgressTotal(progressInfo.FileIndex, fileInfo.Length);

                    uploader.OnTransferProgress =
                        (sender, args) =>
                    {
                        if (args.Progress.TotalBytes > 0)
                        {
                            progressInfo.ProgressTransferred(progressInfo.FileIndex, args.Progress.BytesTransferred);
                        }
                    };

                    Task.Run(() => uploader.UploadAsync()).Wait();
                    fileSupportDelegate(fileInfo.Name);
                }
            }
        }
        /// <summary>
        /// Execute all actions list in parallel (threads)
        /// </summary>
        internal void Execute()
        {
            int remainingCounter = ActionsQueue.Count;

            if (remainingCounter > 0)
            {
                int maxParallelThreads = System.Environment.ProcessorCount * 2;
                int runningThreads = 0;
                int threadIndex = 1;

                while (remainingCounter > 0)
                {
                    // if actions queue is not empty and current running threads are less than the allowed max parallel threads count
                    if (ActionsQueue.Count > 0 && runningThreads < maxParallelThreads)
                    {
                        runningThreads++;
                        IAction downloadAction = ActionsQueue.Dequeue();

                        Task t = Task.Factory.StartNew(() =>
                        {
                            try
                            {
                                ProgressInfo fileProgressInfo = new ProgressInfo();
                                fileProgressInfo.ProgressTransferred = this.ProgressDone;
                                fileProgressInfo.ProgressTotal = this.ProgressTotal;
                                fileProgressInfo.FileIndex = threadIndex;

                                ProgressInfoList.Add(threadIndex++, fileProgressInfo);

                                downloadAction.CopyFileItem(fileProgressInfo);
                            }
                            catch (Exception error)
                            {
                                Log.Logger.Instance.Error(error.Message);
                            }
                            remainingCounter--;
                            runningThreads--;
                        });
                    }

                    UpdateProgress();
                    Thread.Sleep(1000);
                }


                UpdateProgress();
                Thread.Sleep(1000);
            }
        }
        /// <summary>
        /// Execute all actions list in parallel (threads)
        /// </summary>
        internal void Execute()
        {
            int remainingCounter = ActionsQueue.Count;

            if (remainingCounter > 0)
            {
                int maxParallelThreads = System.Environment.ProcessorCount * 2;
                int runningThreads     = 0;
                int threadIndex        = 1;

                while (remainingCounter > 0)
                {
                    // if actions queue is not empty and current running threads are less than the allowed max parallel threads count
                    if (ActionsQueue.Count > 0 && runningThreads < maxParallelThreads)
                    {
                        runningThreads++;
                        IAction downloadAction = ActionsQueue.Dequeue();

                        Task t = Task.Factory.StartNew(() =>
                        {
                            try
                            {
                                ProgressInfo fileProgressInfo        = new ProgressInfo();
                                fileProgressInfo.ProgressTransferred = this.ProgressDone;
                                fileProgressInfo.ProgressTotal       = this.ProgressTotal;
                                fileProgressInfo.FileIndex           = threadIndex;

                                ProgressInfoList.Add(threadIndex++, fileProgressInfo);

                                downloadAction.CopyFileItem(fileProgressInfo);
                            }
                            catch (Exception error)
                            {
                                Log.Logger.Instance.Error(error.Message);
                            }
                            remainingCounter--;
                            runningThreads--;
                        });
                    }

                    UpdateProgress();
                    Thread.Sleep(1000);
                }


                UpdateProgress();
                Thread.Sleep(1000);
            }
        }
        /// <summary>
        /// Execute all actions list in parallel (threads)
        /// </summary>
        internal void Execute()
        {
            int remainingCounter = ActionsQueue.Count;

            if (remainingCounter > 0)
            {
                int maxParallelThreads = System.Environment.ProcessorCount * 2;
                int runningThreads     = 0;
                int threadIndex        = 1;

                while (remainingCounter > 0)
                {
                    // if actions queue is not empty and current running threads are less than the allowed max parallel threads count
                    if (ActionsQueue.Count > 0 && runningThreads < maxParallelThreads)
                    {
                        Interlocked.Increment(ref runningThreads);
                        IAction downloadAction = ActionsQueue.Dequeue();
                        Task    t = Task.Factory.StartNew(async() =>
                        {
                            for (int i = 1; i <= 7; i++)
                            {
                                try
                                {
                                    ProgressInfo fileProgressInfo        = new ProgressInfo();
                                    fileProgressInfo.ProgressTransferred = this.ProgressDone;
                                    fileProgressInfo.ProgressTotal       = this.ProgressTotal;
                                    fileProgressInfo.FileIndex           = threadIndex;

                                    ProgressInfoList.Add(threadIndex++, fileProgressInfo);
                                    if (i > 1)
                                    {
                                        // This means that this is a retry. In that case force the operation
                                        // Otherwise file already exists error is thrown
                                        downloadAction.OpActionType = ActionType.Force;
                                        downloadAction.CopyFileItem(fileProgressInfo);
                                    }
                                    else
                                    {
                                        downloadAction.CopyFileItem(fileProgressInfo);
                                    }
                                    // Task completed, break out of the loop.
                                    Log.Logger.Instance.Debug("Action on Filename : " + downloadAction.FileName + " got completed in " + i + " try");
                                    break;
                                }
                                catch (AggregateException tce)
                                {
                                    // This means ShareFile Client Api has cancelled the task.
                                    // Retry the operation.
                                    Log.Logger.Instance.Error(tce.Message + " Upload/Download action for " + downloadAction.FileName + "\n" + tce.StackTrace);

                                    if (i == 7)
                                    {
                                        // No need to wait
                                        break;
                                    }
                                    // Wait for sometime before retrying the operation
                                    double timeToWait = Math.Pow(2, i);
                                    await Task.Delay(TimeSpan.FromSeconds(timeToWait));
                                }
                                catch (Exception e)
                                {
                                    // This means operation failed due to some other reasons.
                                    // No need to retry, break out of the loop.
                                    Log.Logger.Instance.Error(e.Message + "\n" + e.StackTrace);
                                    break;
                                }
                            }
                            Interlocked.Decrement(ref remainingCounter);
                            Interlocked.Decrement(ref runningThreads);
                        });
                    }

                    UpdateProgress();
                    Thread.Sleep(1000);
                }


                UpdateProgress();
                Thread.Sleep(1000);
            }
        }