private Movie GetMatchingMovie(string movieName, int?movieYear, string targetFolder, FileOrganizationResult result)
        {
            var parsedName = _libraryManager.ParseName(movieName);

            var yearInName      = parsedName.Year;
            var nameWithoutYear = parsedName.Name;

            if (string.IsNullOrWhiteSpace(nameWithoutYear))
            {
                nameWithoutYear = movieName;
            }

            if (!yearInName.HasValue)
            {
                yearInName = movieYear;
            }

            result.ExtractedName = nameWithoutYear;
            result.ExtractedYear = yearInName;

            var movie = _libraryManager.GetItemList(new InternalItemsQuery
            {
                IncludeItemTypes = new[] { BaseItemKind.Movie },
                Recursive        = true,
                DtoOptions       = new DtoOptions(true),
            })
                        .Cast <Movie>()
                        .Select(i => NameUtils.GetMatchScore(nameWithoutYear, yearInName, i))
                        .Where(i => i.Item2 > 0)
                        .OrderByDescending(i => i.Item2)
                        .Select(i => i.Item1)
                        .FirstOrDefault(m =>

                                        // Check For the right folder AND the right extension (to handle quality upgrade)
                                        m.Path.StartsWith(targetFolder, StringComparison.Ordinal) &&
                                        Path.GetExtension(m.Path) == Path.GetExtension(result.OriginalPath));

            return(movie);
        }
        private Series GetMatchingSeries(string seriesName, int?seriesYear, string targetFolder, FileOrganizationResult result)
        {
            if (result != null)
            {
                result.ExtractedName = seriesName;
                result.ExtractedYear = seriesYear;
            }

            var series = _libraryManager.GetItemList(new InternalItemsQuery
            {
                IncludeItemTypes = new[] { BaseItemKind.Series },
                Recursive        = true,
                DtoOptions       = new DtoOptions(true)
            })
                         .Cast <Series>()
                         .Select(i => NameUtils.GetMatchScore(seriesName, seriesYear, i))
                         .Where(i => i.Item2 > 0)
                         .OrderByDescending(i => i.Item2)
                         .Select(i => i.Item1)
                         .FirstOrDefault(s => s.Path.StartsWith(targetFolder, StringComparison.Ordinal));

            if (series == null)
            {
                var info = _organizationService.GetSmartMatchInfos().Items.FirstOrDefault(e => e.MatchStrings.Contains(seriesName, StringComparer.OrdinalIgnoreCase));

                if (info != null)
                {
                    series = _libraryManager.GetItemList(new InternalItemsQuery
                    {
                        IncludeItemTypes = new[] { BaseItemKind.Series },
                        Recursive        = true,
                        Name             = info.ItemName,
                        DtoOptions       = new DtoOptions(true)
                    }).Cast <Series>().FirstOrDefault(s => s.Path.StartsWith(targetFolder, StringComparison.Ordinal));
                }
            }

            return(series);
        }
        private async Task <Tuple <Movie, RemoteSearchResult> > AutoDetectMovie(string movieName, int?movieYear, FileOrganizationResult result, MovieFileOrganizationOptions options, CancellationToken cancellationToken)
        {
            if (options.AutoDetectMovie)
            {
                var parsedName = _libraryManager.ParseName(movieName);

                var yearInName                 = parsedName.Year;
                var nameWithoutYear            = parsedName.Name;
                RemoteSearchResult finalResult = null;

                if (string.IsNullOrWhiteSpace(nameWithoutYear))
                {
                    nameWithoutYear = movieName;
                }

                if (!yearInName.HasValue)
                {
                    yearInName = movieYear;
                }

                // Perform remote search
                var movieInfo = new MovieInfo {
                    Name = nameWithoutYear, Year = yearInName,
                };
                var searchResultsTask = await _providerManager.GetRemoteSearchResults <Movie, MovieInfo>(
                    new RemoteSearchQuery <MovieInfo> {
                    SearchInfo = movieInfo
                },
                    cancellationToken).ConfigureAwait(false);

                // Group movies by name and year (if 2 movie with the exact same name, the same year ...)
                var groupedResult = searchResultsTask.GroupBy(
                    p => new { p.Name, p.ProductionYear },
                    p => p,
                    (key, g) => new { Key = key, Result = g.ToList() }).ToList();

                if (groupedResult.Count == 1)
                {
                    finalResult = groupedResult.First().Result.First();
                }
                else if (groupedResult.Count > 1)
                {
                    var filtredResult = groupedResult
                                        .Select(i => new { Ref = i, Score = NameUtils.GetMatchScore(nameWithoutYear, yearInName, i.Key.Name, i.Key.ProductionYear) })
                                        .Where(i => i.Score > 0)
                                        .OrderByDescending(i => i.Score)
                                        .Select(i => i.Ref)
                                        .FirstOrDefault();
                    finalResult = filtredResult?.Result.First();
                }

                if (finalResult != null)
                {
                    // We are in the good position, we can create the item
                    var organizationRequest = new MovieFileOrganizationRequest
                    {
                        NewMovieName        = finalResult.Name,
                        NewMovieProviderIds = finalResult.ProviderIds,
                        NewMovieYear        = finalResult.ProductionYear,
                        TargetFolder        = options.DefaultMovieLibraryPath
                    };

                    var movie = CreateNewMovie(organizationRequest, result, options);

                    return(new Tuple <Movie, RemoteSearchResult>(movie, finalResult));
                }
            }

            return(null);
        }