using ErsatzTV.Core; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Repositories; using static ErsatzTV.Application.Libraries.Mapper; namespace ErsatzTV.Application.Libraries; public class CreateLocalLibraryPathHandler : IRequestHandler> { private readonly ILibraryRepository _libraryRepository; public CreateLocalLibraryPathHandler(ILibraryRepository libraryRepository) => _libraryRepository = libraryRepository; public Task> Handle( CreateLocalLibraryPath request, CancellationToken cancellationToken) => Validate(request).MapT(PersistLocalLibraryPath).Bind(v => v.ToEitherAsync()); private Task PersistLocalLibraryPath(LibraryPath p) => _libraryRepository.Add(p).Map(ProjectToViewModel); private Task> Validate(CreateLocalLibraryPath request) => ValidateFolder(request) .MapT( folder => new LibraryPath { LibraryId = request.LibraryId, Path = folder }); private async Task> ValidateFolder(CreateLocalLibraryPath request) { List allPaths = await _libraryRepository.GetLocalPaths(request.LibraryId) .Map(list => list.Map(c => c.Path).ToList()); return Optional(request.Path) .Where(folder => allPaths.ForAll(f => !AreSubPaths(f, folder))) .ToValidation("Path must not belong to another library path"); } private static bool AreSubPaths(string path1, string path2) { string one = path1 + Path.DirectorySeparatorChar; string two = path2 + Path.DirectorySeparatorChar; return one == two || one.StartsWith(two, StringComparison.OrdinalIgnoreCase) || two.StartsWith(one, StringComparison.OrdinalIgnoreCase); } }