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),
];
}
}