using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using ErsatzTV.Core; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Plex; using ErsatzTV.Core.Interfaces.Repositories; using LanguageExt; using MediatR; namespace ErsatzTV.Application.MediaSources.Commands { public class SynchronizePlexMediaSourcesHandler : IRequestHandler>> { private readonly IMediaSourceRepository _mediaSourceRepository; private readonly IPlexTvApiClient _plexTvApiClient; public SynchronizePlexMediaSourcesHandler( IMediaSourceRepository mediaSourceRepository, IPlexTvApiClient plexTvApiClient) { _mediaSourceRepository = mediaSourceRepository; _plexTvApiClient = plexTvApiClient; } public Task>> Handle( SynchronizePlexMediaSources request, CancellationToken cancellationToken) => _plexTvApiClient.GetServers().BindAsync(SynchronizeAllServers); private async Task>> SynchronizeAllServers( List servers) { List allExisting = await _mediaSourceRepository.GetAllPlex(); foreach (PlexMediaSource server in servers) { await SynchronizeServer(allExisting, server); } return allExisting; } private async Task SynchronizeServer(List allExisting, PlexMediaSource server) { Option maybeExisting = allExisting.Find(s => s.ClientIdentifier == server.ClientIdentifier); await maybeExisting.Match( existing => { existing.ProductVersion = server.ProductVersion; existing.Name = server.Name; MergeConnections(existing.Connections, server.Connections); if (existing.Connections.Any() && existing.Connections.All(c => !c.IsActive)) { existing.Connections.Head().IsActive = true; } return _mediaSourceRepository.Update(existing); }, async () => { await _mediaSourceRepository.Add(server); if (server.Connections.Any()) { server.Connections.Head().IsActive = true; } await _mediaSourceRepository.Update(server); }); } private void MergeConnections( List existing, List incoming) { var toAdd = incoming.Filter(connection => existing.All(c => c.Uri != connection.Uri)).ToList(); var toRemove = existing.Filter(connection => incoming.All(c => c.Uri != connection.Uri)).ToList(); existing.AddRange(toAdd); toRemove.ForEach(c => existing.Remove(c)); } } }