public void PerformOrganization(MovieFileOrganizationRequest request)
        {
            var organizer = new MovieFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager,
                                                   _libraryMonitor, _providerManager);

            var options = GetAutoOrganizeOptions();
            var result  = organizer.OrganizeWithCorrection(request, options.MovieOptions, CancellationToken.None);
        }
        /// <inheritdoc/>
        public async Task PerformOrganization(MovieFileOrganizationRequest request)
        {
            var organizer = new MovieFileOrganizer(this, _fileSystem, _logger, _libraryManager, _libraryMonitor, _providerManager);

            var options = _config.GetAutoOrganizeOptions();
            var result  = await organizer.OrganizeWithCorrection(request, options.MovieOptions, CancellationToken.None).ConfigureAwait(false);

            if (result.Status != FileSortingStatus.Success)
            {
                throw new Exception(result.StatusMessage);
            }
        }
        /// <inheritdoc/>
        public async Task PerformOrganization(string resultId)
        {
            var result = _repo.GetResult(resultId);

            var options = _config.GetAutoOrganizeOptions();

            if (string.IsNullOrEmpty(result.TargetPath))
            {
                throw new ArgumentException("No target path available.");
            }

            FileOrganizationResult organizeResult;

            switch (result.Type)
            {
            case FileOrganizerType.Episode:
                var episodeOrganizer = new EpisodeFileOrganizer(
                    this,
                    _fileSystem,
                    _loggerFactory.CreateLogger <EpisodeFileOrganizer>(),
                    _libraryManager,
                    _libraryMonitor,
                    _providerManager);
                organizeResult = await episodeOrganizer.OrganizeEpisodeFile(result.OriginalPath, options.TvOptions, CancellationToken.None)
                                 .ConfigureAwait(false);

                break;

            case FileOrganizerType.Movie:
                var movieOrganizer = new MovieFileOrganizer(
                    this,
                    _fileSystem,
                    _loggerFactory.CreateLogger <MovieFileOrganizer>(),
                    _libraryManager,
                    _libraryMonitor,
                    _providerManager);
                organizeResult = await movieOrganizer.OrganizeMovieFile(result.OriginalPath, options.MovieOptions, true, CancellationToken.None)
                                 .ConfigureAwait(false);

                break;

            default:
                throw new OrganizationException("No organizer exist for the type " + result.Type);
            }

            if (organizeResult.Status != FileSortingStatus.Success)
            {
                throw new OrganizationException(result.StatusMessage);
            }
        }
        /// <summary>
        /// Perform organization for the movie watch folders.
        /// </summary>
        /// <param name="options">The organization options.</param>
        /// <param name="progress">The <see cref="IProgress{T}"/> to use for reporting operation progress.</param>
        /// <param name="cancellationToken">A cancellation token for the operation.</param>
        /// <returns>A task representing the operation completion.</returns>
        public async Task Organize(
            MovieFileOrganizationOptions options,
            IProgress <double> progress,
            CancellationToken cancellationToken)
        {
            // Get all valid watch locations
            var libraryFolderPaths = _libraryManager.GetVirtualFolders().SelectMany(i => i.Locations).ToList();
            var watchLocations     = options.WatchLocations
                                     .Where(i => IsValidWatchLocation(i, libraryFolderPaths))
                                     .ToList();

            var eligibleFiles = watchLocations.SelectMany(GetFilesToOrganize)
                                .OrderBy(_fileSystem.GetCreationTimeUtc)
                                .Where(i => CanOrganize(i, options))
                                .ToList();

            var processedFolders = new HashSet <string>();

            progress.Report(10);

            if (eligibleFiles.Count > 0)
            {
                var numComplete = 0;

                var organizer = new MovieFileOrganizer(_organizationService, _fileSystem, _logger, _libraryManager, _libraryMonitor, _providerManager);

                foreach (var file in eligibleFiles)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    try
                    {
                        var result = await organizer.OrganizeMovieFile(file.FullName, options, options.OverwriteExistingFiles, cancellationToken).ConfigureAwait(false);

                        if (result.Status == FileSortingStatus.Success && !processedFolders.Contains(file.DirectoryName, StringComparer.OrdinalIgnoreCase))
                        {
                            processedFolders.Add(file.DirectoryName);
                        }
                    }
                    catch (OperationCanceledException)
                    {
                        break;
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "Error organizing episode {0}", file.FullName);
                    }

                    numComplete++;
                    double percent = numComplete;
                    percent /= eligibleFiles.Count;

                    progress.Report(10 + (89 * percent));
                }
            }

            cancellationToken.ThrowIfCancellationRequested();
            progress.Report(99);

            List <string> deleteExtensions = options.LeftOverFileExtensionsToDelete
                                             .Select(i => i.Trim().TrimStart('.'))
                                             .Where(i => !string.IsNullOrEmpty(i))
                                             .Select(i => "." + i)
                                             .ToList();

            // Normal Clean
            Clean(processedFolders, watchLocations, options.DeleteEmptyFolders, deleteExtensions);

            // Extended Clean
            if (options.ExtendedClean)
            {
                Clean(watchLocations, watchLocations, options.DeleteEmptyFolders, deleteExtensions);
            }

            progress.Report(100);
        }