using System;
using System.Collections.Generic;
using System.Linq;
namespace Pf2e.WPF.EntityViewer.EntityViewStructure;
///
/// Класс для построения структуры данных класса.
///
internal class StructureBuilder
{
///
/// Список обработанных объектов.
///
private readonly List _processedObjects = [];
///
/// Создание поля структуры.
///
/// Название поля.
/// Значение поля.
/// Глубина, на котором поле отображается.
/// Поле структуры.
public StructureFieldComplex Create(string name, object value, int depth = 0)
{
_ = RegisterProcessed(value);
StructureFieldComplex field = new(this, value, name, depth);
CompleteProcessed(value, field);
return field;
}
///
/// Регистрация обработанного объекта.
///
/// Регистрируемый объект.
/// `true`, если объект был добавлен; `false`, если объект был добавлен ранее.
public bool RegisterProcessed(object value)
{
if (_processedObjects.Any(p => p.Value == value))
{
return false;
}
StructureProcessedObject processed = new(value);
_processedObjects.Add(processed);
return true;
}
///
/// Дополнить обработанный объект.
///
/// Значение.
/// Поле объекта.
public void CompleteProcessed(object value, StructureFieldComplex field)
{
StructureProcessedObject? q = _processedObjects.FirstOrDefault(p => p.Value == value);
if (q == null)
{
return;
}
q.Field = field;
}
///
/// Выбор поля структуры по значению.
///
/// Название поля.
/// Значение поля.
/// Глубина, на котором поле отображается.
///
public StructureField Resolve(string name, object? value, int depth)
{
switch (GetFieldType(value))
{
case StructureFieldType.Null:
return new StructureFieldNull(this, name, depth);
case StructureFieldType.Primitive:
return new StructureFieldPrimitive(this, value!, name, depth);
case StructureFieldType.Enum:
return new StructureFieldEnum(this, value!, name, depth);
case StructureFieldType.Reference:
break;
case StructureFieldType.Complex:
default:
StructureProcessedObject? processed = _processedObjects.FirstOrDefault(p =>
p.Value == value
);
if (processed is null)
{
return Create(name, value!, depth);
}
StructureFieldReference reference = new(this, name, null, depth);
processed.AddReference(reference);
return reference;
}
throw new("Impossible");
}
///
/// Получить тип поля структуры по значению.
///
/// Значение поля.
/// Тип поля структуры.
public static StructureFieldType GetFieldType(object? value)
{
if (value is null)
{
return StructureFieldType.Null;
}
Type type = value.GetType();
if (type.IsEnum)
{
return StructureFieldType.Enum;
}
if (type.IsPrimitive || type == typeof(string))
{
return StructureFieldType.Primitive;
}
return StructureFieldType.Complex;
}
}