MyBookmark/Modules.Library.Domain/Entities/MediaContent/CommonProperties/CommonProperties.cs
2024-09-23 03:00:50 +03:00

280 lines
10 KiB
C#

namespace Modules.Library.Domain.Entities.MediaContent.CommonProperties;
public class CommonProperties : ValueObject
{
private readonly List<NameItem> _names = [];
public IReadOnlyCollection<NameItem> Names => _names.AsReadOnly();
public MediaInfo? Preview { get; private set; }
private readonly List<Description> _descriptions = [];
public IReadOnlyCollection<Description> Descriptions => _descriptions.AsReadOnly();
private readonly List<GenreProportion> _genres = [];
public IReadOnlyCollection<GenreProportion> Genres => _genres.AsReadOnly();
private readonly List<MediaInfo> _relatedContent = [];
public IReadOnlyCollection<MediaInfo> RelatedContent => _relatedContent.AsReadOnly();
public DateTimeOffset? AnnouncementDate { get; private set; }
public DateTimeOffset? EstimatedReleaseDate { get; private set; }
public DateTimeOffset? ReleaseDate { get; private set; }
internal CommonProperties() { }
private CommonProperties(Models.CommonProperties commonProperties)
{
Preview = commonProperties.Preview != null ? new MediaInfo(commonProperties.Preview.Url, commonProperties.Preview.Type) : null;
AnnouncementDate = commonProperties.AnnouncementDate;
EstimatedReleaseDate = commonProperties.EstimatedReleaseDate;
ReleaseDate = commonProperties.ReleaseDate;
_names.AddRange(commonProperties.Names.Select(NameItem.New));
_descriptions.AddRange(commonProperties.Descriptions.Select(Description.New));
_genres.AddRange(commonProperties.Genres.Select(GenreProportion.New));
_relatedContent.AddRange(commonProperties.RelatedContent.Select(q => new MediaInfo(q.Url, q.Type)));
}
internal CommonProperties(Guid nameOriginalLnaguageId, string nameOriginal)
{
_names.Add(new NameItem(nameOriginalLnaguageId, NameType.Original, nameOriginal));
}
internal static CommonProperties New(Models.CommonProperties commonProperties) => new(commonProperties);
#region Name
public void AddName(NameType nameType, Guid languageId, string value)
{
switch (nameType)
{
case NameType.Original:
AddNameOriginal(languageId, value);
break;
case NameType.OriginalInAnotherLanguage:
AddNameOriginalInAnotherLanguage(languageId, value);
break;
case NameType.Translation:
AddNameTranslation(languageId, value);
break;
case NameType.Abbreviation:
AddNameAbbreviation(languageId, value);
break;
default:
throw new NotImplementedException();
}
}
private void AddNameOriginal(Guid languageId, string value)
{
if (_names.Any(q => q.Type == NameType.Original)) throw new Exception("Original name is already exist.");
var name = new NameItem(languageId, NameType.Original, value);
_names.Add(name);
}
private void AddNameOriginalInAnotherLanguage(Guid languageId, string value)
{
if (_names.FirstOrDefault(q => q.Type == NameType.Original)?.LanguageId == languageId)
throw new Exception("Language must not match original name language");
if (_names.Any(q => q.Type == NameType.OriginalInAnotherLanguage && q.LanguageId == languageId))
throw new Exception("Name in following language is already exist.");
var name = new NameItem(languageId, NameType.OriginalInAnotherLanguage, value);
_names.Add(name);
}
private void AddNameTranslation(Guid languageId, string value)
{
var name = new NameItem(languageId, NameType.Translation, value);
_names.Add(name);
}
private void AddNameAbbreviation(Guid languageId, string value)
{
var name = new NameItem(languageId, NameType.Abbreviation, value);
_names.Add(name);
}
public void RemoveName(NameItem nameItem)
{
var name = GetName(nameItem);
if (name.Type == NameType.Original) throw new Exception($"Unable to remove original name");
_names.Remove(name);
}
public void SetNameValue(NameItem nameItem, string value)
{
var name = GetName(nameItem);
if (string.IsNullOrWhiteSpace(value)) throw new ArgumentNullException(nameof(value));
if (nameItem.Type != NameType.Original && _names.Any(q => q.LanguageId == nameItem.LanguageId && q.Value == value))
throw new Exception("Name item with in same language with same value is already exists");
nameItem.SetValue(value);
}
private NameItem GetName(NameItem name) => _names.FirstOrDefault(q => q == name) ??
throw new Exception($"Name with is not found");
#endregion
public void SetPreview(string url, MediaInfoType type)
{
if (string.IsNullOrWhiteSpace(url)) throw new ArgumentNullException(nameof(url));
Preview ??= new MediaInfo(url, type);
Preview.SetUrl(url);
Preview.SetType(type);
}
public void DeletePreview() => Preview = null;
#region Description
public void AddOriginalDescription(Guid languageId, string value)
{
if (_descriptions.Any(q => q.IsOriginal)) throw new Exception("Original description is already exist.");
var description = new Description(languageId, true, value);
_descriptions.Add(description);
}
public void AddNotOriginalDescription(Guid languageId, string value)
{
var description = new Description(languageId, false, value);
_descriptions.Add(description);
}
public void RemoveDescription(Description descriptionItem)
{
var description = GetDescription(descriptionItem);
if (description.IsOriginal) throw new Exception($"Unable to remove original description");
_descriptions.Remove(description); //TODO: valueobject convert
//description.SetDeleted();
}
public void SetDescriptionValue(Description descriptionItem, string value)
{
var description = GetDescription(descriptionItem);
if (string.IsNullOrWhiteSpace(value)) throw new ArgumentNullException(nameof(value));
if (!descriptionItem.IsOriginal && _descriptions.Any(q => q.LanguageId == descriptionItem.LanguageId && q.Value == value))
throw new Exception("Descriptoin item with with same value is already exists");
descriptionItem.SetValue(value);
}
private Description GetDescription(Description description)
{
return _descriptions.FirstOrDefault(q => q == description) ??
throw new Exception($"Description is not found");
}
#endregion
#region Genre
public void AddGenre(Guid genreId, decimal? proportion = null)
{
if (_genres.Any(q => q.GenreId == genreId)) throw new Exception("Genre is already in the list");
var genreProportionItem = new GenreProportion(genreId, proportion);
_genres.Add(genreProportionItem);
if (proportion.HasValue) genreProportionItem.SetProportion(proportion);
}
public void SetGenreProportion(Guid genreId, decimal? value = null)
{
var genreProportion = GetGenreProportionItem(genreId);
genreProportion.SetProportion(value);
}
public void RemoveGenre(Guid genreId)
{
var genreProportion = GetGenreProportionItem(genreId);
_genres.Remove(genreProportion);
}
private GenreProportion GetGenreProportionItem(Guid genreId)
{
return _genres.FirstOrDefault(q => q.GenreId == genreId) ??
throw new Exception($"Genre proportion is not found");
}
/*
private GenreProportion GetGenreProportionItem(GenreProportion genreProportionItem)
{
return _genres.FirstOrDefault(q => q == genreProportionItem) ??
throw new Exception($"Genre proportion is not found");
}
*/
#endregion
#region RelatedContent
public void AddRelatedContent(string url, MediaInfoType type)
{
if (string.IsNullOrWhiteSpace(url)) throw new ArgumentNullException(nameof(url));
CheckIfCanAddOrEdit(url, type);
_relatedContent.Add(new MediaInfo(url, type));
}
public void EditRelatedContent(MediaInfo relatedContentItem, string url, MediaInfoType type)
{
var relatedContent = GetRelatedContent(relatedContentItem);
CheckIfCanAddOrEdit(url, type);
relatedContent.SetUrl(url);
relatedContent.SetType(type);
}
public void RemoveRelatedContent(MediaInfo relatedContentItem)
{
var relatedContent = GetRelatedContent(relatedContentItem);
_relatedContent.Remove(relatedContent); //TODO: valueobject convert
}
private void CheckIfCanAddOrEdit(string url, MediaInfoType type)
{
if (_relatedContent.Any(q => q.Url == url && q.Type == type))
throw new Exception("Related content with same url and same type is already exists");
}
private MediaInfo GetRelatedContent(MediaInfo relatedContentItem)
{
return _relatedContent.FirstOrDefault(q => q == relatedContentItem) ??
throw new Exception($"Related content is not found");
}
#endregion
public void SetAnnouncementDate(DateTimeOffset? value)
{
AnnouncementDate = value;
}
public void SetEstimatedReleaseDate(DateTimeOffset? value)
{
if (value == default) throw new ArgumentNullException(nameof(value));
if (AnnouncementDate.HasValue && value <= AnnouncementDate.Value)
throw new Exception("Estimated release date can not be less or equal to announcement date");
EstimatedReleaseDate = value;
}
public void SetReleaseDate(DateTimeOffset? value)
{
if (value == default) throw new ArgumentNullException(nameof(value));
if (AnnouncementDate.HasValue && value <= AnnouncementDate.Value)
throw new Exception("Release date can not be less or equal to announcement date");
ReleaseDate = value;
}
protected override IEnumerable<object?> GetEqualityComponents()
{
foreach (var name in _names)
{
yield return name;
}
yield return Preview;
foreach (var descriptions in _descriptions)
{
yield return descriptions;
}
foreach (var genre in _genres)
{
yield return genre;
}
foreach (var relatedContent in _relatedContent)
{
yield return relatedContent;
}
yield return AnnouncementDate;
yield return EstimatedReleaseDate;
yield return ReleaseDate;
}
}