/// <summary>
        /// Upload contents recursively
        /// </summary>
        private void UploadRecursive(ShareFileClient client, int uploadId, FileSystemInfo source, Models.Item target, ActionType actionType)
        {
            if (source is DirectoryInfo)
            {
                var newFolder = new Models.Folder() { Name = source.Name };
                bool isExist = false;

                if (Synchronize)
                {
                    try
                    {
                        string path = String.Format("/{0}", source.Name);
                        Item item = null;
                        try
                        {
                            item = client.Items.ByPath(target.url, path).Execute();
                        }
                        catch (ODataException e)
                        {
                            if (e.Code != System.Net.HttpStatusCode.NotFound)
                            {
                                throw e;
                            }
                        }

                        if (item != null && item is Folder)
                        {
                            isExist = true;
                            newFolder = (Folder)item;
                        }
                    }
                    catch { }
                }

                if (!isExist)
                {
                    newFolder = client.Items.CreateFolder(target.url, newFolder, OverWrite, false).Execute();
                }

                ActionManager actionManager = new ActionManager(this, source.Name);

                foreach (var fsInfo in ((DirectoryInfo)source).EnumerateFileSystemInfos())
                {
                    if (fsInfo is DirectoryInfo && Recursive)
                    {
                        UploadRecursive(client, uploadId, fsInfo, newFolder, actionType);
                    }
                    else if (fsInfo is FileInfo)
                    {
                        IAction uploadAction = new UploadAction(FileSupport, client, fsInfo, newFolder, Details, actionType);
                        actionManager.AddAction(uploadAction);
                    }
                }

                actionManager.Execute();
            }
        }
        /// <summary>
        /// Start Upload to Sharefile location
        /// </summary>
        private void StartUpload(ShareFileClient client, int uploadId, Models.Item target, ICollection<string> resolvedPaths, ActionType actionType)
        {
            int transactionId = new Random((int)DateTime.Now.Ticks).Next();

            ActionManager actionManager = new ActionManager(this, string.Empty);
            bool firstIteration = true;

            foreach (string path in resolvedPaths)
            {
                FileAttributes attr = System.IO.File.GetAttributes(path);
                FileSystemInfo source = ((attr & FileAttributes.Directory) == FileAttributes.Directory) ? new DirectoryInfo(path) : source = new FileInfo(path);

                // create an extra parent folder if CreateRoot flag is specified on target location
                if (firstIteration && CreateRoot)
                {
                    DirectoryInfo parentFolder = Directory.GetParent(path);
                    var newFolder = new Models.Folder() { Name = parentFolder.Name };
                    target = client.Items.CreateFolder(target.url, newFolder, OverWrite, false).Execute();
                    firstIteration = false;
                }

                if (source is DirectoryInfo)
                {
                    UploadRecursive(client, uploadId, source, target, actionType);
                }
                else
                {
                    IAction uploadAction = new UploadAction(FileSupport, client, source, target, Details, actionType);
                    actionManager.AddAction(uploadAction);
                }
            }

            actionManager.Execute();

            if (Strict)
            {
                foreach (string path in resolvedPaths)
                {
                    FileAttributes attr = System.IO.File.GetAttributes(path);
                    if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
                    {
                        DirectoryInfo source = new DirectoryInfo(path);

                        var children = client.Items.GetChildren(target.url).Execute();
                        
                        foreach (var child in children.Feed)
                        {
                            if (child is Models.Folder && child.Name.Equals(source.Name))
                            {
                                DeleteSharefileStrictRecursive(client, source as DirectoryInfo, child);
                                break;
                            }
                        }
                    }
                }
            }

            if (Move)
            {
                foreach (string path in resolvedPaths)
                {
                    FileAttributes attr = System.IO.File.GetAttributes(path);
                    FileSystemInfo source = ((attr & FileAttributes.Directory) == FileAttributes.Directory) ? new DirectoryInfo(path) : source = new FileInfo(path);

                    DeleteLocalItemRecursive(source, Recursive);
                }
            }
        }
        /// <summary>
        /// Download all items recursively
        /// </summary>
        private void DownloadRecursive(ShareFileClient client, int downloadId, Models.Item source, DirectoryInfo target, ActionType actionType)
        {
            if (source is Models.Folder)
            {
                var subdir = CreateLocalFolder(target, source as Folder);

                var children = client.Items.GetChildren(source.url).Execute();

                if (children != null)
                {
                    ActionManager actionManager = new ActionManager(this, source.Name);

                    foreach (var child in children.Feed)
                    {
                        if (child is Models.Folder && Recursive)
                        {
                            DownloadRecursive(client, downloadId, child, subdir, actionType);
                        }
                        else if (child is Models.File)
                        {
                            DownloadAction downloadAction = new DownloadAction(FileSupport, client, downloadId, (Models.File)child, subdir, actionType);
                            actionManager.AddAction(downloadAction);
                        }
                    }

                    actionManager.Execute();
                }
            }
        }
        /// <summary>
        /// Start download process
        /// </summary>
        private void StartDownload(ShareFileClient client, PSDriveInfo driveInfo, ICollection<string> resolvedPaths, ActionType actionType)
        {
            int transactionId = new Random((int)DateTime.Now.Ticks).Next();

            ActionManager actionManager = new ActionManager(this, string.Empty);
            bool firstIteration = true;

            foreach (string path in resolvedPaths)
            {
                var item = Utility.ResolveShareFilePath(driveInfo, path);

                if (item == null)
                {
                    throw new FileNotFoundException(string.Format("Source path '{0}' not found on ShareFile server.", path));
                }

                var target = new DirectoryInfo(LocalPath);

                if (!target.Exists)
                {
                    throw new Exception(string.Format("Destination '{0}' path not found on local drive.", LocalPath));
                }

                // if create root folder flag is specified then create a container folder first
                if (firstIteration && CreateRoot)
                {
                    Models.Folder parentFolder = client.Items.GetParent(item.url).Execute() as Folder;

                    target = CreateLocalFolder(target, parentFolder);
                    firstIteration = false;
                }

                if (item is Models.Folder)
                {
                    // if user downloading the root drive then download its root folders
                    if ((item as Folder).Info.IsAccountRoot == true)
                    {
                        var children = client.Items.GetChildren(item.url).Execute();
                        foreach (var child in children.Feed)
                        {
                            if (child is Models.Folder)
                            {
                                DownloadRecursive(client, transactionId, child, target, actionType);
                            }
                        }
                    }
                    else
                    {
                        DownloadRecursive(client, transactionId, item, target, actionType);
                    }
                }
                else if (item is Models.File)
                {
                    DownloadAction downloadAction = new DownloadAction(FileSupport, client, transactionId, (Models.File)item, target, actionType);
                    actionManager.AddAction(downloadAction);
                }
            }

            actionManager.Execute();

            // if strict flag is specified then also clean the target files which are not in source
            if (Strict)
            {
                var target = new DirectoryInfo(LocalPath);
                var directories = target.GetDirectories();

                foreach (string path in resolvedPaths)
                {
                    var item = Utility.ResolveShareFilePath(driveInfo, path);
                    
                    if (item is Folder)
                    {
                        foreach (DirectoryInfo directory in directories)
                        {
                            if (directory.Name.Equals(item.Name))
                            {
                                DeleteLocalStrictRecursive(client, item, directory);
                                break;
                            }
                        }
                    }
                }
            }

            // on move remove source files
            if (Move)
            {
                foreach (string path in resolvedPaths)
                {
                    var item = ShareFileProvider.GetShareFileItem((ShareFileDriveInfo)driveInfo, path, null, null);
                    var target = new DirectoryInfo(LocalPath);

                    DeleteShareFileItemRecursive(client, item, CreateRoot && Recursive);
                }
            }
        }
        private void RecursiveDownload(ShareFileClient client, int downloadId, Models.Item source, DirectoryInfo target)
        {
            if (source is Models.Folder)
            {
                var children = client.Items.GetChildren(source.url).Execute();
                var subdirCheck = new DirectoryInfo(System.IO.Path.Combine(target.FullName, source.FileName));
                if (subdirCheck.Exists && !Force && !ResumeSupport.IsPending) throw new IOException("Path " + subdirCheck.FullName + " already exists. Use -Force to ignore");
                var subdir = target.CreateSubdirectory(source.FileName);
                if (children != null)
                {
                    ActionManager actionManager = new ActionManager(this, source.FileName);

                    foreach (var child in children.Feed)
                    {

                        if (child is Models.Folder)
                        {
                            RecursiveDownload(client, downloadId, child, subdir);
                        }
                        else if (child is Models.File)
                        {
                            if (!ResumeSupport.IsPending || !ResumeSupport.CheckFileStatus(child.FileName))
                            {
                                ActionType actionType = Force || ResumeSupport.IsPending ? ActionType.Force : ActionType.None;
                                DownloadAction downloadAction = new DownloadAction(FileSupport, client, downloadId, (Models.File)child, subdir, actionType);
                                actionManager.AddAction(downloadAction);
                            }
                        }
                    }

                    actionManager.Execute();
                }
            }
            else if (source is Models.File)
            {
                ActionManager actionManager = new ActionManager(this, source.FileName);
                if (!ResumeSupport.IsPending || !ResumeSupport.CheckFileStatus(source.FileName))
                {
                    ActionType actionType = Force || ResumeSupport.IsPending ? ActionType.Force : ActionType.None;
                    DownloadAction downloadAction = new DownloadAction(FileSupport, client, downloadId, (Models.File)source, target, actionType);
                    actionManager.AddAction(downloadAction);
                }
                actionManager.Execute();
            }
        }
        private void RecursiveUpload(ShareFileClient client, int uploadId, FileSystemInfo source, Models.Item target)
        {
            if (source is DirectoryInfo)
            {
                var newFolder = new Models.Folder() { Name = source.Name };
                newFolder = client.Items.CreateFolder(target.url, newFolder, Force || ResumeSupport.IsPending, false).Execute();

                ActionManager actionManager = new ActionManager(this, source.Name);
                ActionType actionType = Force ? ActionType.Force : ActionType.None;

                foreach (var fsInfo in ((DirectoryInfo)source).EnumerateFileSystemInfos())
                {
                    if (fsInfo is DirectoryInfo)
                    {
                        RecursiveUpload(client, uploadId, fsInfo, newFolder);
                    }
                    else if (fsInfo is FileInfo)
                    {
                        if (!ResumeSupport.IsPending || !ResumeSupport.CheckFileStatus(fsInfo.Name))
                        {
                            IAction uploadAction = new UploadAction(FileSupport, client, fsInfo, newFolder, Details, actionType);
                            actionManager.AddAction(uploadAction);
                        }
                    }
                }

                actionManager.Execute();
            }
            else if (source is FileInfo)
            {
                ActionManager actionManager = new ActionManager(this, source.Name);
                if (!ResumeSupport.IsPending || !ResumeSupport.CheckFileStatus(source.Name))
                {
                    ActionType actionType = Force || ResumeSupport.IsPending ? ActionType.Force : ActionType.None;
                    IAction uploadAction = new UploadAction(FileSupport, client, source, target, Details, actionType);
                    actionManager.AddAction(uploadAction);
                }
                actionManager.Execute();
            }
        }