using System.Collections; using System.ComponentModel; using Pf2e.Database.Model; using Pf2e.Database.Model.Base.Keywords; using Pf2e.Database.Model.Base.Source; using Pf2e.Database.Model.Base.Targets; using Pf2e.Database.Model.Common.I18n; using Pf2e.Database.Model.Enum; namespace Pf2e.Web.Helpers; public class EntityFieldFormatter { /// /// Форматировать значение для отображения. /// public string? FormatValue(object? value) { if (value == null) return null; Type type = value.GetType(); foreach (ValueFormatter formatter in _formatters) { if (formatter.CanFormat(type)) { return formatter.Format(value); } } return null; } /// /// Абстрактный класс форматтера значений. /// private abstract class ValueFormatter { /// /// Проверяет, может ли форматтер обработать указанный тип. /// /// Тип значения. /// true, если форматтер может обработать тип, иначе false. public abstract bool CanFormat(Type type); /// /// Форматирует значение для отображения. /// /// Значение для форматирования. /// Строковое представление отформатированного значения. public abstract string Format(object value); } /// /// Форматтер для конкретного типа. /// /// Тип значения. /// Функция форматирования значения. private class TypeValueFormatter(Func formatter) : ValueFormatter { public override bool CanFormat(Type type) => type == typeof(T); public override string Format(object value) => formatter(value); } /// /// Форматтер с пользовательскими функциями проверки и форматирования. /// /// Функция проверки типа. /// Функция форматирования значения. private class CustomValueFormatter(Func checker, Func formatter) : ValueFormatter { public override bool CanFormat(Type type) => checker(type); public override string Format(object value) => formatter(value); } /// /// Форматтер для коллекций. /// private class CollectionFormatter(EntityFieldFormatter fieldFormatter) : ValueFormatter { public override bool CanFormat(Type type) => typeof(IEnumerable).IsAssignableFrom(type) && type != typeof(string); public override string Format(object value) { IEnumerable collection = (IEnumerable)value; List items = []; foreach (object? item in collection) { string? itemDisplay = fieldFormatter.FormatValue(item); items.Add(itemDisplay ?? "null"); } return items.Count == 0 ? "(empty)" : string.Join("
", items); } } /// /// Коллекция форматтеров. /// private readonly List _formatters; /// /// Получить описание элемента перечисления из DescriptionAttribute. /// /// Элемент перечисления. /// Описание или имя элемента, если атрибут не найден. private static string GetEnumDescription(Enum value) { Type type = value.GetType(); string name = Enum.GetName(type, value) ?? value.ToString(); System.Reflection.FieldInfo? field = type.GetField(name); if (field == null) return value.ToString(); if ( Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attr ) { return attr.Description; } return value.ToString(); } /// /// Конструктор EntitySerializer. /// public EntityFieldFormatter() { _formatters = [ // Форматтеры для перечислений new CustomValueFormatter( (type) => type.IsEnum, (value) => { Enum enumValue = (Enum)value; string description = GetEnumDescription(enumValue); return $"{description} ({enumValue})"; } ), // Примитивные типы new CustomValueFormatter( (type) => type.IsPrimitive || type == typeof(string) || type == typeof(decimal), (value) => value.ToString() ?? "null" ), // LocaleString new TypeValueFormatter( (value) => { LocaleString localeString = (LocaleString)value; List items = []; foreach (LocaleItem item in localeString) { items.Add($"{item.Locale}: {item.Value}"); } return string.Join("
", items); } ), // IEntity new CustomValueFormatter( (type) => typeof(IEntity).IsAssignableFrom(type), (value) => { IEntity entity = (IEntity)value; EntityType entityType = entity.Entity.Type; string typeName = PgNameHelper.GetPgName(entityType); string slug = entity.Entity.Slug; string name = entity.Entity.Name[LocaleType.English]; return $"{name}"; } ), // EntitySource new TypeValueFormatter( (value) => { EntitySource entitySource = (EntitySource)value; string sourceName = entitySource.Source.Name; string suffix = !string.IsNullOrEmpty(entitySource.Suffix) ? $" ({entitySource.Suffix})" : ""; string isRemaster = entitySource.IsRemaster ? " [Remaster]" : ""; return $"{sourceName}{suffix}{isRemaster}"; } ), // Keyword new TypeValueFormatter( (value) => { Keyword keyword = (Keyword)value; string name = keyword.Name[LocaleType.English]; return $"{name}"; } ), // KeywordAlias new TypeValueFormatter( (value) => { KeywordAlias alias = (KeywordAlias)value; return $"{alias.Value}"; } ), // ExternalTarget new TypeValueFormatter( (value) => { ExternalTarget target = (ExternalTarget)value; return $"{target.Name} (Icon: {target.Icon}, Prefix: {target.Prefix})"; } ), // EntityExternal new TypeValueFormatter( (value) => { EntityExternal entityExternal = (EntityExternal)value; string targetName = entityExternal.Target?.Name ?? "Unknown"; string externalId = !string.IsNullOrEmpty(entityExternal.ExternalId) ? $" ID: {entityExternal.ExternalId}" : ""; string suffix = !string.IsNullOrEmpty(entityExternal.Suffix) ? $" Suffix: {entityExternal.Suffix}" : ""; return $"{targetName}{externalId}{suffix}"; } ), // Source new TypeValueFormatter( (value) => { Source source = (Source)value; string releaseDate = source.ReleaseDate?.ToString("yyyy-MM-dd") ?? "Unknown"; return $"{source.Name} (Category: {source.Category}, Release: {releaseDate})"; } ), // Коллекции new CollectionFormatter(this), ]; } }