using Modules.Library.Domain.EntitiesV0.MediaContent.CommonProperties.ShadowEntities; namespace Modules.Library.Domain.EntitiesV0.MediaContent.CommonProperties; public class CommonProperties : Entity { private readonly CommonPropertiesShadow _shadow; public IReadOnlyCollection Names => _shadow.names.AsReadOnly(); public MediaInfo? Preview => _shadow.preview; public IReadOnlyCollection Descriptions => _shadow.descriptions.AsReadOnly(); public IReadOnlyCollection Genres => _shadow.genres.AsReadOnly(); public IReadOnlyCollection RelatedContent => _shadow.relatedContent.AsReadOnly(); public DateTimeOffset? AnnouncementDate => _shadow.announcementDate; internal Action? AfterAnnouncementDateSet; public DateTimeOffset? EstimatedReleaseDate => _shadow.estimatedReleaseDate; internal Action? AfterEstimatedReleaseDateSet; public DateTimeOffset? ReleaseDate => _shadow.releaseDate; internal Action? AfterReleaseDateSet; public override bool Deleted => false; internal CommonProperties(CommonPropertiesShadow shadow, Action? afterAnnouncementDateSet, Action? afterEstimatedReleaseDateSet, Action? afterReleaseDateSet) { _shadow = shadow; AfterAnnouncementDateSet = afterAnnouncementDateSet; AfterEstimatedReleaseDateSet = afterEstimatedReleaseDateSet; AfterReleaseDateSet = afterReleaseDateSet; } #region Name internal void AddNameOriginal(string languageId, string value) { if (_shadow.names.Any(q => q.Type == NameType.Original)) throw new Exception("Original name is already exist."); var name = new NameItem(languageId, NameType.Original, value); AddName(name, value); } internal void AddNameOriginalInAnotherLanguage(string languageId, string value) { if (languageId == _shadow.names.Single(q => q.Type == NameType.Original).LanguageId) throw new Exception("Language must not match original name language"); if (_shadow.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); AddName(name, value); } internal void AddNameTranslation(string languageId, string value) { var name = new NameItem(languageId, NameType.Translation); AddName(name, value); } internal void AddNameAbbreviation(string languageId, string value) { var name = new NameItem(languageId, NameType.Abbreviation); AddName(name, value); } private void AddName(NameItem nameItem, string value) { _shadow.names.Add(nameItem); SetNameValue(nameItem, value); } internal void RemoveName(string nameId) { var name = GetName(nameId); if (name.Type == NameType.Original) throw new Exception($"Unable to remove original name"); name.SetDeleted(); //_names.Remove(name); } internal void SetNameValue(string nameId, string value) => SetNameValue(GetName(nameId), value); private void SetNameValue(NameItem nameItem, string value) { if (string.IsNullOrWhiteSpace(value)) throw new ArgumentNullException(nameof(value)); if (nameItem.Type != NameType.Original && _shadow.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(string nameId) => _shadow.names.FirstOrDefault(q => q.Id == nameId) ?? throw new Exception($"Name with id [{nameId}] is not found"); #endregion internal void SetPreview(string url, MediaInfoType type) { if (string.IsNullOrWhiteSpace(url)) throw new ArgumentNullException(nameof(url)); _shadow.preview ??= new MediaInfo(url, type); _shadow.preview.SetUrl(url); } internal void DeletePreview() { _shadow.preview = null; } #region Description internal void AddOriginalDescription(string languageId, string value) { if (_shadow.descriptions.Any(q => q.IsOriginal)) throw new Exception("Original description is already exist."); var description = new DescriptionItem(languageId, true); _shadow.descriptions.Add(description); SetDescriptionValue(description, value); } internal void AddNotOriginalDescription(string languageId, string value) { var description = new DescriptionItem(languageId, false); _shadow.descriptions.Add(description); SetDescriptionValue(description, value); } internal void RemoveDescription(string descriptionId) { var description = GetDescription(descriptionId); if (description.IsOriginal) throw new Exception($"Unable to remove original description"); //_descriptions.Remove(name); description.SetDeleted(); } internal void SetDescriptionValue(string descriptionId, string value) { var name = GetDescription(descriptionId); SetDescriptionValue(name, value); } private void SetDescriptionValue(DescriptionItem descriptionItem, string value) { if (string.IsNullOrWhiteSpace(value)) throw new ArgumentNullException(nameof(value)); if (!descriptionItem.IsOriginal && _shadow.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 DescriptionItem GetDescription(string descriptionId) { return _shadow.descriptions.FirstOrDefault(q => q.Id == descriptionId) ?? throw new Exception($"Description with id [{descriptionId}] is not found"); } #endregion #region Genre internal void AddGenre(string genreId, decimal? proportion = null) { if (_shadow.genres.Any(q => q.GenreId == genreId)) throw new Exception("Genre is already in the list"); var genreProportionItem = new GenreProportionItem(genreId); _shadow.genres.Add(genreProportionItem); if (proportion.HasValue) genreProportionItem.SetProportion(proportion); } internal void SetGenreProportion(string genreProportionItemId, decimal? value = null) { var genreProportionItem = GetGenreProportionItem(genreProportionItemId); genreProportionItem.SetProportion(value); } internal void RemoveGenre(string genreProportionItemId) { var genreProportionItem = GetGenreProportionItem(genreProportionItemId); //_genres.Remove(genreProportionItem); genreProportionItem.SetDeleted(); } private GenreProportionItem GetGenreProportionItem(string genreProportionItemId) { return _shadow.genres.FirstOrDefault(q => q.Id == genreProportionItemId) ?? throw new Exception($"Genre proportion item with id [{genreProportionItemId}] is not found"); } #endregion #region RelatedContent internal void AddRelatedContent(string url, MediaInfoType type) { if (string.IsNullOrWhiteSpace(url)) throw new ArgumentNullException(nameof(url)); CheckIfCanAddOrEdit(url, type); _shadow.relatedContent.Add(new MediaInfo(url, type)); } internal void EditRelatedContent(string relatedContentId, string url, MediaInfoType type) { var relatedContent = GetRelatedContent(relatedContentId); CheckIfCanAddOrEdit(url, type); relatedContent.SetUrl(url); relatedContent.SetType(type); } internal void RemoveRelatedContent(string relatedContentId) { var relatedContent = GetRelatedContent(relatedContentId); //_relatedContent.Remove(relatedContent); relatedContent.SetDeleted(); } private void CheckIfCanAddOrEdit(string url, MediaInfoType type) { if (_shadow.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(string relatedContentId) { return _shadow.relatedContent.FirstOrDefault(q => q.Id == relatedContentId) ?? throw new Exception($"Related content with id [{relatedContentId}] is not found"); } #endregion internal void SetAnnouncementDate(DateTimeOffset value) { if (value == default) throw new ArgumentNullException(nameof(value)); _shadow.announcementDate = value; AfterAnnouncementDateSet?.Invoke(); } internal void SetEstimatedReleaseDate(DateTimeOffset value) { if (value == default) throw new ArgumentNullException(nameof(value)); if (_shadow.announcementDate.HasValue && value <= _shadow.announcementDate.Value) throw new Exception("Estimated release date can not be less or equal to announcement date"); _shadow.estimatedReleaseDate = value; AfterEstimatedReleaseDateSet?.Invoke(); } internal void SetReleaseDate(DateTimeOffset value) { if (value == default) throw new ArgumentNullException(nameof(value)); if (_shadow.announcementDate.HasValue && value <= _shadow.announcementDate.Value) throw new Exception("Release date can not be less or equal to announcement date"); _shadow.releaseDate = value; AfterReleaseDateSet?.Invoke(); } internal override void SetDeleted() { } }