129 lines
5.4 KiB
C#
129 lines
5.4 KiB
C#
namespace TeleWave.Domain.Library;
|
|
|
|
/// <summary>
|
|
/// Переиспользуемое шоу в общей библиотеке: сериал (упорядоченные серии) либо полнометражка.
|
|
/// Серии идут строго в порядке <see cref="ShowEpisode.Position"/>; курсор показа на канале хранится
|
|
/// отдельно на связке канал↔шоу (см. Broadcast/ChannelShow).
|
|
/// </summary>
|
|
public class Show
|
|
{
|
|
private readonly List<ShowEpisode> _episodes = new();
|
|
|
|
public Guid Id { get; private set; }
|
|
public string Name { get; private set; } = string.Empty;
|
|
|
|
/// <summary>Оригинальное название (обычно на английском) — по нему ищутся метаданные; на экранах
|
|
/// продолжаем показывать <see cref="Name"/>. Null/пусто — ищем по <see cref="Name"/>.</summary>
|
|
public string? OriginalName { get; private set; }
|
|
|
|
public string? Description { get; private set; }
|
|
public ShowKind Kind { get; private set; }
|
|
public DateTimeOffset CreatedAt { get; private set; }
|
|
|
|
// ── Метаданные (TMDb/OMDb/вручную) ──
|
|
/// <summary>Источник метаданных: «tmdb»/«omdb»/«manual» или null, если не заданы.</summary>
|
|
public string? MetadataProvider { get; private set; }
|
|
|
|
/// <summary>Идентификатор шоу во внешнем источнике (для довыгрузки серий).</summary>
|
|
public string? MetadataExternalId { get; private set; }
|
|
|
|
public int? Year { get; private set; }
|
|
|
|
/// <summary>Постер шоу — ссылка на запись общего реестра изображений (<c>Domain/Images</c>) или null.</summary>
|
|
public Guid? PosterImageId { get; private set; }
|
|
|
|
/// <summary>Серии шоу (backing-field для EF). Порядок показа — по <see cref="ShowEpisode.Position"/>;
|
|
/// потребители сортируют явно (см. загрузчик планировщика).</summary>
|
|
public IReadOnlyList<ShowEpisode> Episodes => _episodes;
|
|
|
|
private Show() { }
|
|
|
|
public static Show Create(
|
|
string name,
|
|
ShowKind kind,
|
|
string? description = null,
|
|
string? originalName = null
|
|
) =>
|
|
new()
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
Name = name,
|
|
OriginalName = Normalize(originalName),
|
|
Kind = kind,
|
|
Description = description,
|
|
CreatedAt = DateTimeOffset.UtcNow,
|
|
};
|
|
|
|
public void Rename(string name, string? description)
|
|
{
|
|
Name = name;
|
|
Description = description;
|
|
}
|
|
|
|
/// <summary>Задать/снять оригинальное название (пустая строка трактуется как отсутствие).</summary>
|
|
public void SetOriginalName(string? originalName) => OriginalName = Normalize(originalName);
|
|
|
|
private static string? Normalize(string? value) =>
|
|
string.IsNullOrWhiteSpace(value) ? null : value.Trim();
|
|
|
|
/// <summary>Добавляет серию в конец. Для <see cref="ShowKind.Single"/> допустима ровно одна серия.</summary>
|
|
public ShowEpisode AddEpisode(Guid mediaAssetId)
|
|
{
|
|
var nextPosition = _episodes.Count == 0 ? 0 : _episodes.Max(e => e.Position) + 1;
|
|
var episode = ShowEpisode.Create(Id, mediaAssetId, nextPosition);
|
|
_episodes.Add(episode);
|
|
return episode;
|
|
}
|
|
|
|
public bool RemoveEpisode(Guid episodeId)
|
|
{
|
|
var episode = _episodes.FirstOrDefault(e => e.Id == episodeId);
|
|
if (episode is null)
|
|
return false;
|
|
_episodes.Remove(episode);
|
|
return true;
|
|
}
|
|
|
|
public bool CanAddEpisode => Kind != ShowKind.Single || _episodes.Count == 0;
|
|
|
|
/// <summary>Применить метаданные из внешнего источника. Постер (уже зарегистрирован в реестре) может быть null.</summary>
|
|
public void ApplyMetadata(
|
|
string provider,
|
|
string externalId,
|
|
string? description,
|
|
int? year,
|
|
Guid? posterImageId
|
|
)
|
|
{
|
|
MetadataProvider = provider;
|
|
MetadataExternalId = externalId;
|
|
if (!string.IsNullOrWhiteSpace(description))
|
|
Description = description;
|
|
Year = year;
|
|
if (posterImageId is not null)
|
|
PosterImageId = posterImageId;
|
|
}
|
|
|
|
/// <summary>Ручная правка метаданных (без внешнего источника).</summary>
|
|
public void UpdateMetadataManual(string? description, int? year)
|
|
{
|
|
MetadataProvider = "manual";
|
|
MetadataExternalId = null;
|
|
Description = description;
|
|
Year = year;
|
|
}
|
|
|
|
/// <summary>Привязать/снять постер шоу (ссылка на запись реестра изображений).</summary>
|
|
public void SetPosterImage(Guid? imageId) => PosterImageId = imageId;
|
|
|
|
/// <summary>Сбросить все метаданные и отвязать постер (сама картинка остаётся в галерее).</summary>
|
|
public void ClearMetadata()
|
|
{
|
|
MetadataProvider = null;
|
|
MetadataExternalId = null;
|
|
Year = null;
|
|
PosterImageId = null;
|
|
Description = null;
|
|
}
|
|
}
|