using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using CommunityToolkit.Diagnostics;
using OwlCore.Events;
using OwlCore.Extensions;
using StrixMusic.Sdk.CoreModels;
using StrixMusic.Sdk.Extensions;
using StrixMusic.Sdk.FileMetadata;
using StrixMusic.Sdk.FileMetadata.Models;
using StrixMusic.Sdk.MediaPlayback;
namespace StrixMusic.Cores.Files.Models
{
///
/// Wraps around to provide playlist information extracted from a file to the Strix SDK.
///
public sealed class LocalFilesCorePlaylist : ICorePlaylist
{
private readonly IFileMetadataManager? _fileMetadataManager;
private PlaylistMetadata _playlistMetadata;
///
/// Creates a new instance of
///
public LocalFilesCorePlaylist(ICore sourceCore, PlaylistMetadata playlistMetadata)
{
SourceCore = sourceCore;
_playlistMetadata = playlistMetadata;
Guard.IsNotNull(playlistMetadata, nameof(playlistMetadata));
Guard.IsNotNullOrWhiteSpace(playlistMetadata.Id, nameof(playlistMetadata.Id));
Id = playlistMetadata.Id;
_fileMetadataManager = sourceCore.Cast().FileMetadataManager;
Duration = playlistMetadata.Duration ?? default;
AttachEvents();
}
private void AttachEvents()
{
Guard.IsNotNull(_fileMetadataManager, nameof(_fileMetadataManager));
_fileMetadataManager.Playlists.MetadataUpdated += Albums_MetadataUpdated;
}
private void DetachEvents()
{
Guard.IsNotNull(_fileMetadataManager, nameof(_fileMetadataManager));
_fileMetadataManager.Playlists.MetadataUpdated -= Albums_MetadataUpdated;
}
///
public event EventHandler? IsPlayTrackCollectionAsyncAvailableChanged;
///
public event EventHandler? IsPauseTrackCollectionAsyncAvailableChanged;
///
public event EventHandler? TracksCountChanged;
///
public event EventHandler? ImagesCountChanged;
///
public event EventHandler? UrlsCountChanged;
///
public event EventHandler? PlaybackStateChanged;
///
public event EventHandler? NameChanged;
///
public event EventHandler? DescriptionChanged;
///
public event EventHandler? DurationChanged;
///
public event EventHandler? LastPlayedChanged;
///
public event EventHandler? IsChangeNameAsyncAvailableChanged;
///
public event EventHandler? IsChangeDescriptionAsyncAvailableChanged;
///
public event EventHandler? IsChangeDurationAsyncAvailableChanged;
///
public event CollectionChangedEventHandler? TracksChanged;
///
public event CollectionChangedEventHandler? ImagesChanged;
///
public event CollectionChangedEventHandler? UrlsChanged;
///
public ICore SourceCore { get; }
///
public string Id { get; set; }
///
public string Name => _playlistMetadata.Title ?? string.Empty;
///
public string? Description => _playlistMetadata.Description;
///
public DateTime? LastPlayed { get; }
///
public PlaybackState PlaybackState { get; }
///
public TimeSpan Duration { get; private set; }
///
public bool IsChangeNameAsyncAvailable => false;
///
public bool IsChangeDescriptionAsyncAvailable => false;
///
public bool IsChangeDurationAsyncAvailable => false;
///
public ICoreUserProfile? Owner { get; }
///
public ICorePlayableCollectionGroup? RelatedItems { get; }
///
public DateTime? AddedAt { get; }
///
public int TotalTrackCount => _playlistMetadata.TrackIds?.Count ?? 0;
///
public int TotalImageCount { get; }
///
public int TotalUrlCount { get; }
///
public bool IsPlayTrackCollectionAsyncAvailable => false;
///
public bool IsPauseTrackCollectionAsyncAvailable => false;
///
public Task ChangeNameAsync(string name, CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
///
public Task ChangeDescriptionAsync(string? description, CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
///
public Task ChangeDurationAsync(TimeSpan duration, CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
///
public Task IsAddTrackAvailableAsync(int index, CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
///
public Task IsAddImageAvailableAsync(int index, CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
///
public Task IsAddUrlAvailableAsync(int index, CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
///
public Task IsRemoveTrackAvailableAsync(int index, CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
///
public Task IsRemoveImageAvailableAsync(int index, CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
///
public Task IsRemoveUrlAvailableAsync(int index, CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
///
public Task AddImageAsync(ICoreImage image, int index, CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
///
public Task AddUrlAsync(ICoreUrl image, int index, CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
///
public Task AddTrackAsync(ICoreTrack track, int index, CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
///
public Task RemoveImageAsync(int index, CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
///
public Task RemoveUrlAsync(int index, CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
///
public Task RemoveTrackAsync(int index, CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
///
public Task PlayTrackCollectionAsync(ICoreTrack track, CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
/// A cancellation token that may be used to cancel the ongoing task.
///
public Task PlayTrackCollectionAsync(CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
/// A cancellation token that may be used to cancel the ongoing task.
///
public Task PauseTrackCollectionAsync(CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
///
public async IAsyncEnumerable GetTracksAsync(int limit, int offset, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
Guard.IsNotNull(_fileMetadataManager, nameof(_fileMetadataManager));
var trackIds = _playlistMetadata.TrackIds;
Guard.IsNotNull(trackIds, nameof(trackIds));
foreach (var id in trackIds)
{
cancellationToken.ThrowIfCancellationRequested();
var track = await _fileMetadataManager.Tracks.GetByIdAsync(id);
Guard.IsNotNull(track, nameof(track));
yield return new FilesCoreTrack(SourceCore, track);
}
}
///
public IAsyncEnumerable GetImagesAsync(int limit, int offset, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
///
public IAsyncEnumerable GetUrlsAsync(int limit, int offset, CancellationToken cancellationToken = default)
{
return AsyncEnumerable.Empty();
}
private void Albums_MetadataUpdated(object sender, IEnumerable e)
{
foreach (var metadata in e)
{
if (metadata.Id != Id)
return;
var previousData = _playlistMetadata;
_playlistMetadata = metadata;
if (metadata.Title != previousData.Title)
NameChanged?.Invoke(this, Name);
if (metadata.Description != previousData.Description)
DescriptionChanged?.Invoke(this, Description);
if (metadata.Duration != previousData.Duration)
DurationChanged?.Invoke(this, Duration);
if (metadata.TrackIds?.Count != previousData.TrackIds?.Count)
TracksCountChanged?.Invoke(this, metadata.TrackIds?.Count ?? 0);
}
}
///
public ValueTask DisposeAsync()
{
DetachEvents();
return default;
}
}
}