context: using System.Collections.Generic;
  using System.IO;
  using System.Linq;
  using FizzWare.NBuilder;
  using FluentAssertions;
  using Moq;
  using NUnit.Framework;
  using NzbDrone.Common.Disk;
  using NzbDrone.Core.Download;
  using NzbDrone.Core.Download.TrackedDownloads;
  using NzbDrone.Core.MediaFiles;
  using NzbDrone.Core.MediaFiles.MovieImport;
  using NzbDrone.Core.Movies;
  using NzbDrone.Core.Parser;
  using NzbDrone.Core.Parser.Model;
  using NzbDrone.Core.Test.Framework;
  using NzbDrone.Test.Common;
  
  namespace NzbDrone.Core.Test.MediaFiles
  {
      [TestFixture]
      public class DownloadedMoviesImportServiceFixture : CoreTest<DownloadedMovieImportService>
      {
          private string _droneFactory = "c:\\drop\\".AsOsAgnostic();
          private string[] _subFolders = new[] { "c:\\root\\foldername".AsOsAgnostic() };
          private string[] _videoFiles = new[] { "c:\\root\\foldername\\47.ronin.2013.ext".AsOsAgnostic() };
  
          private TrackedDownload _trackedDownload;
  
          [SetUp]
          public void Setup()
          {
              ParseMovieTitle();
  
              //UseRealParsingService();
              Mocker.GetMock<IDiskScanService>().Setup(c => c.GetVideoFiles(It.IsAny<string>(), It.IsAny<bool>()))
                    .Returns(_videoFiles);
  
              Mocker.GetMock<IDiskScanService>().Setup(c => c.FilterPaths(It.IsAny<string>(), It.IsAny<IEnumerable<string>>(), It.IsAny<bool>()))
                    .Returns<string, IEnumerable<string>, bool>((b, s, e) => s.ToList());
  
              Mocker.GetMock<IDiskProvider>().Setup(c => c.GetDirectories(It.IsAny<string>()))
                    .Returns(_subFolders);
  
              Mocker.GetMock<IDiskProvider>().Setup(c => c.FolderExists(It.IsAny<string>()))
                    .Returns(true);
  
              Mocker.GetMock<IImportApprovedMovie>()
                    .Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), true, null, ImportMode.Auto))
                    .Returns(new List<ImportResult>());
  
              var downloadItem = Builder<DownloadClientItem>.CreateNew()
                  .With(v => v.DownloadId = "sab1")
                  .With(v => v.Status = DownloadItemStatus.Downloading)
                  .Build();
  
              var remoteMovie = Builder<RemoteMovie>.CreateNew()
                  .With(v => v.Movie = new Movie())
                  .Build();
  
              _trackedDownload = new TrackedDownload
              {
                  DownloadItem = downloadItem,
                  RemoteMovie = remoteMovie,
                  State = TrackedDownloadState.Downloading
              };
          }
  
          private void GivenValidMovie()
          {
              Mocker.GetMock<IParsingService>()
                    .Setup(s => s.GetMovie(It.IsAny<string>()))
                    .Returns(Builder<Movie>.CreateNew().Build());
          }
  
          private void GivenSuccessfulImport()
          {
              var localMovie = new LocalMovie();
  
              var imported = new List<ImportDecision>();
              imported.Add(new ImportDecision(localMovie));
  
              Mocker.GetMock<IMakeImportDecision>()
                    .Setup(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Movie>(), It.IsAny<DownloadClientItem>(), null, true, true))
                    .Returns(imported);
  
              Mocker.GetMock<IImportApprovedMovie>()
                    .Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), It.IsAny<bool>(), It.IsAny<DownloadClientItem>(), It.IsAny<ImportMode>()))
                    .Returns(imported.Select(i => new ImportResult(i)).ToList())
                    .Callback(() => WasImportedResponse());
          }
  
          private void WasImportedResponse()
          {
              Mocker.GetMock<IDiskScanService>().Setup(c => c.GetVideoFiles(It.IsAny<string>(), It.IsAny<bool>()))
                    .Returns(System.Array.Empty<string>());
          }
  
          [Test]
          public void should_search_for_series_using_folder_name()
          {
              Subject.ProcessRootFolder(new DirectoryInfo(_droneFactory));
  
              Mocker.GetMock<IParsingService>().Verify(c => c.GetMovie("foldername"), Times.Once());
          }
  
          [Test]
          public void should_skip_if_file_is_in_use_by_another_process()
          {
              GivenValidMovie();
  
              Mocker.GetMock<IDiskProvider>().Setup(c => c.IsFileLocked(It.IsAny<string>()))
                    .Returns(true);
  
              Subject.ProcessRootFolder(new DirectoryInfo(_droneFactory));
  
              VerifyNoImport();
          }
  
          [Test]
          public void should_skip_if_no_series_found()
          {
              Mocker.GetMock<IParsingService>().Setup(c => c.GetMovie("foldername")).Returns((Movie)null);
  
              Subject.ProcessRootFolder(new DirectoryInfo(_droneFactory));
  
              Mocker.GetMock<IMakeImportDecision>()
                  .Verify(c => c.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Movie>(), It.IsAny<DownloadClientItem>(), It.IsAny<ParsedMovieInfo>(), It.IsAny<bool>()),
                      Times.Never());
  
              VerifyNoImport();
          }
  
          [Test]
          public void should_not_import_if_folder_is_a_series_path()
          {
              GivenValidMovie();
  
              Mocker.GetMock<IMovieService>()
                    .Setup(s => s.MoviePathExists(It.IsAny<string>()))
                    .Returns(true);
  
              Mocker.GetMock<IDiskScanService>()
                    .Setup(c => c.GetVideoFiles(It.IsAny<string>(), It.IsAny<bool>()))
                    .Returns(System.Array.Empty<string>());
  
              Subject.ProcessRootFolder(new DirectoryInfo(_droneFactory));
  
              Mocker.GetMock<IDiskScanService>()
                    .Verify(v => v.GetVideoFiles(It.IsAny<string>(), true), Times.Never());
  
              ExceptionVerification.ExpectedWarns(1);
          }
  
          [Test]
          public void should_not_delete_folder_if_no_files_were_imported()
          {
              Mocker.GetMock<IImportApprovedMovie>()
                    .Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), false, null, ImportMode.Auto))
                    .Returns(new List<ImportResult>());
  
              Subject.ProcessRootFolder(new DirectoryInfo(_droneFactory));
  
              Mocker.GetMock<IDiskProvider>()
                    .Verify(v => v.GetFolderSize(It.IsAny<string>()), Times.Never());
          }
  
          [Test]
          public void should_not_delete_folder_after_import()
          {
              GivenValidMovie();
  
              GivenSuccessfulImport();
  
              _trackedDownload.DownloadItem.CanMoveFiles = false;
  
              Subject.ProcessPath(_droneFactory, ImportMode.Auto, _trackedDownload.RemoteMovie.Movie, _trackedDownload.DownloadItem);
  
              Mocker.GetMock<IDiskProvider>()
                    .Verify(v => v.DeleteFolder(It.IsAny<string>(), true), Times.Never());
          }
  
          [Test]
          public void should_delete_folder_if_importmode_move()
          {
              GivenValidMovie();
  
              GivenSuccessfulImport();
  
              _trackedDownload.DownloadItem.CanMoveFiles = false;
  
              Subject.ProcessPath(_droneFactory, ImportMode.Move, _trackedDownload.RemoteMovie.Movie, _trackedDownload.DownloadItem);
  
              Mocker.GetMock<IDiskProvider>()
                    .Verify(v => v.DeleteFolder(It.IsAny<string>(), true), Times.Once());
          }
  
          [Test]
          public void should_not_delete_folder_if_importmode_copy()
          {
              GivenValidMovie();
  
              GivenSuccessfulImport();
  
              _trackedDownload.DownloadItem.CanMoveFiles = true;
  
              Subject.ProcessPath(_droneFactory, ImportMode.Copy, _trackedDownload.RemoteMovie.Movie, _trackedDownload.DownloadItem);
  
              Mocker.GetMock<IDiskProvider>()
                    .Verify(v => v.DeleteFolder(It.IsAny<string>(), true), Times.Never());
          }
  
          [Test]
          public void should_not_delete_folder_if_files_were_imported_and_video_files_remain()
          {
              GivenValidMovie();
  
              var localMovie = new LocalMovie();
  
              var imported = new List<ImportDecision>();
              imported.Add(new ImportDecision(localMovie));
  
              Mocker.GetMock<IMakeImportDecision>()
                    .Setup(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Movie>(), It.IsAny<DownloadClientItem>(), null, true))
                    .Returns(imported);
  
              Mocker.GetMock<IImportApprovedMovie>()
                    .Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), true, null, ImportMode.Auto))
                    .Returns(imported.Select(i => new ImportResult(i)).ToList());
  
              Subject.ProcessRootFolder(new DirectoryInfo(_droneFactory));
  
              Mocker.GetMock<IDiskProvider>()
                    .Verify(v => v.DeleteFolder(It.IsAny<string>(), true), Times.Never());
  
              ExceptionVerification.ExpectedWarns(1);
          }
  
          [Test]
          public void should_delete_folder_if_files_were_imported_and_only_sample_files_remain()
          {
              GivenValidMovie();
  
              var localMovie = new LocalMovie();
  
              var imported = new List<ImportDecision>();
              imported.Add(new ImportDecision(localMovie));
  
              Mocker.GetMock<IMakeImportDecision>()
                    .Setup(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Movie>(), It.IsAny<DownloadClientItem>(), null, true))
                    .Returns(imported);
  
              Mocker.GetMock<IImportApprovedMovie>()
                    .Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), true, null, ImportMode.Auto))
                    .Returns(imported.Select(i => new ImportResult(i)).ToList());
  
              Mocker.GetMock<IDetectSample>()
                    .Setup(s => s.IsSample(It.IsAny<Movie>(),
                        It.IsAny<string>()))
                    .Returns(DetectSampleResult.Sample);
  
              Subject.ProcessRootFolder(new DirectoryInfo(_droneFactory));
  
              Mocker.GetMock<IDiskProvider>()
                    .Verify(v => v.DeleteFolder(It.IsAny<string>(), true), Times.Once());
          }
  
          [TestCase("_UNPACK_")]
          [TestCase("_FAILED_")]
          public void should_remove_unpack_from_folder_name(string prefix)
          {
              var folderName = "47.ronin.2013.hdtv-lol";
              var folders = new[] { string.Format(@"C:\Test\Unsorted\{0}{1}", prefix, folderName).AsOsAgnostic() };
  
              Mocker.GetMock<IDiskProvider>()
                    .Setup(c => c.GetDirectories(It.IsAny<string>()))
                    .Returns(folders);
  
              Subject.ProcessRootFolder(new DirectoryInfo(_droneFactory));
  
              Mocker.GetMock<IParsingService>()
  
gt:                 .Verify(v => v.GetMovie(folderName), Times.Once());