using System.Threading; using System.Threading.Tasks; using ErsatzTV.Core; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Repositories; using LanguageExt; using MediatR; using static ErsatzTV.Application.Channels.Mapper; namespace ErsatzTV.Application.Channels.Commands { public class UpdateChannelHandler : IRequestHandler> { private readonly IChannelRepository _channelRepository; public UpdateChannelHandler(IChannelRepository channelRepository) => _channelRepository = channelRepository; public Task> Handle( UpdateChannel request, CancellationToken cancellationToken) => Validate(request) .MapT(c => ApplyUpdateRequest(c, request)) .Bind(v => v.ToEitherAsync()); private async Task ApplyUpdateRequest(Channel c, UpdateChannel update) { c.Name = update.Name; c.Number = update.Number; c.FFmpegProfileId = update.FFmpegProfileId; c.Logo = update.Logo; c.StreamingMode = update.StreamingMode; await _channelRepository.Update(c); return ProjectToViewModel(c); } private async Task> Validate(UpdateChannel request) => (await ChannelMustExist(request), ValidateName(request), await ValidateNumber(request)) .Apply((channelToUpdate, _, _) => channelToUpdate); private Task> ChannelMustExist(UpdateChannel updateChannel) => _channelRepository.Get(updateChannel.ChannelId) .Map(v => v.ToValidation("Channel does not exist.")); private Validation ValidateName(UpdateChannel updateChannel) => updateChannel.NotEmpty(c => c.Name) .Bind(_ => updateChannel.NotLongerThan(50)(c => c.Name)); private async Task> ValidateNumber(UpdateChannel updateChannel) { Option match = await _channelRepository.GetByNumber(updateChannel.Number); int matchId = match.Map(c => c.Id).IfNone(updateChannel.ChannelId); if (matchId == updateChannel.ChannelId) { return updateChannel.AtLeast(1)(c => c.Number); } return BaseError.New("Channel number must be unique"); } } }