using System.Collections.Generic; using System.IO; using System.Linq; using NLog; using NzbDrone.Core.MediaFiles.Events; using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Tv; using NzbDrone.Core.Tv.Events; using NzbDrone.Common; using System; namespace NzbDrone.Core.MediaFiles { public interface IMediaFileService { MovieFile Add(MovieFile movieFile); void Update(MovieFile movieFile); void Delete(MovieFile movieFile, DeleteMediaFileReason reason); EpisodeFile Add(EpisodeFile episodeFile); void Update(EpisodeFile episodeFile); void Delete(EpisodeFile episodeFile, DeleteMediaFileReason reason); List GetFilesBySeries(int seriesId); List GetFilesByMovie(int movieId); List GetFilesBySeason(int seriesId, int seasonNumber); List GetFilesWithoutMediaInfo(); List FilterExistingFiles(List files, Series series); List FilterExistingFiles(List files, Movie movie); EpisodeFile Get(int id); MovieFile GetMovie(int id); List Get(IEnumerable ids); List GetMovies(IEnumerable ids); //List Get(IEnumerable ids); } public class MediaFileService : IMediaFileService, IHandleAsync, IHandleAsync { private readonly IEventAggregator _eventAggregator; private readonly IMediaFileRepository _mediaFileRepository; private readonly IMovieFileRepository _movieFileRepository; private readonly IMovieService _movieService; private readonly Logger _logger; public MediaFileService(IMediaFileRepository mediaFileRepository, IMovieFileRepository movieFileRepository, IMovieService movieService, IEventAggregator eventAggregator, Logger logger) { _mediaFileRepository = mediaFileRepository; _eventAggregator = eventAggregator; _movieService = movieService; _movieFileRepository = movieFileRepository; _logger = logger; } public EpisodeFile Add(EpisodeFile episodeFile) { var addedFile = _mediaFileRepository.Insert(episodeFile); _eventAggregator.PublishEvent(new EpisodeFileAddedEvent(addedFile)); return addedFile; } public void Update(EpisodeFile episodeFile) { _mediaFileRepository.Update(episodeFile); } public void Delete(EpisodeFile episodeFile, DeleteMediaFileReason reason) { //Little hack so we have the episodes and series attached for the event consumers episodeFile.Episodes.LazyLoad(); episodeFile.Path = Path.Combine(episodeFile.Series.Value.Path, episodeFile.RelativePath); _mediaFileRepository.Delete(episodeFile); _eventAggregator.PublishEvent(new EpisodeFileDeletedEvent(episodeFile, reason)); } public void Delete(MovieFile movieFile, DeleteMediaFileReason reason) { //Little hack so we have the episodes and series attached for the event consumers movieFile.Movie.LazyLoad(); movieFile.Path = Path.Combine(movieFile.Movie.Value.Path, movieFile.RelativePath); _movieFileRepository.Delete(movieFile); _eventAggregator.PublishEvent(new MovieFileDeletedEvent(movieFile, reason)); } public List GetFilesBySeries(int seriesId) { return _mediaFileRepository.GetFilesBySeries(seriesId); } public List GetFilesByMovie(int movieId) { return _movieFileRepository.GetFilesByMovie(movieId); //TODO: Update implementation for movie files. } public List GetFilesBySeason(int seriesId, int seasonNumber) { return _mediaFileRepository.GetFilesBySeason(seriesId, seasonNumber); } public List GetFilesWithoutMediaInfo() { return _mediaFileRepository.GetFilesWithoutMediaInfo(); } public List FilterExistingFiles(List files, Series series) { var seriesFiles = GetFilesBySeries(series.Id).Select(f => Path.Combine(series.Path, f.RelativePath)).ToList(); if (!seriesFiles.Any()) return files; return files.Except(seriesFiles, PathEqualityComparer.Instance).ToList(); } public List FilterExistingFiles(List files, Movie movie) { var movieFiles = GetFilesByMovie(movie.Id).Select(f => Path.Combine(movie.Path, f.RelativePath)).ToList(); if (!movieFiles.Any()) return files; return files.Except(movieFiles, PathEqualityComparer.Instance).ToList(); } public EpisodeFile Get(int id) { return _mediaFileRepository.Get(id); } public List Get(IEnumerable ids) { return _mediaFileRepository.Get(ids).ToList(); } public List GetMovies(IEnumerable ids) { return _movieFileRepository.Get(ids).ToList(); } public void HandleAsync(SeriesDeletedEvent message) { var files = GetFilesBySeries(message.Series.Id); _mediaFileRepository.DeleteMany(files); } public MovieFile Add(MovieFile episodeFile) { var addedFile = _movieFileRepository.Insert(episodeFile); addedFile.Movie.LazyLoad(); if (addedFile.Movie == null || addedFile.Movie.Value == null) { _logger.Error("Movie is null for the file {0}. Please run the houskeeping command to ensure movies and files are linked correctly."); } _movieService.SetFileId(addedFile.Movie.Value, addedFile); //Should not be necessary, but sometimes below fails? _eventAggregator.PublishEvent(new MovieFileAddedEvent(addedFile)); return addedFile; } public void Update(MovieFile movieFile) { _movieFileRepository.Update(movieFile); } public MovieFile GetMovie(int id) { return _movieFileRepository.Get(id); } public void HandleAsync(MovieDeletedEvent message) { if (message.DeleteFiles == true) { var files = GetFilesByMovie(message.Movie.Id); _movieFileRepository.DeleteMany(files); } } } }