Code/UI/Spatial/Node.cs
namespace Nodebox.UI.Spatial;

[Title("Nodebox Spatial Node")]
[Category("Nodebox")]
public partial class Node : Component, IMeta, IGraphStyle {
    [RequireComponent] public NodePanelRoot NodePanelRoot { get; set; }
    [RequireComponent] public Sandbox.WorldPanel WorldPanel { get; set; }

    [JsonIgnore]
    public NodePanel NodePanel => NodePanelRoot?.NodePanel;

    public Dictionary<string, object> Meta => Inner.Meta;

    [JsonIgnore]
    public GraphStyle GraphStyle {
        get => NodePanelRoot.GraphStyle;
        set => NodePanelRoot.GraphStyle = value;
    }

    private Nodebox.Node.Serializable _serializableNode;
    [JsonIgnore]
    [Hide]
    public Nodebox.Node.Serializable SerializableNode {
        get => _serializableNode;
        set {
            Type = value.SerializableType;

            OverridePins = value.Pins.HasValue;
            if (value.Pins.HasValue) {
                (List<Pin> inputPins, List<Pin> outputPins) = value.Pins.Value;
                InputPins.Clear();
                foreach (var pin in inputPins) {
                    InputPins.Add(pin);
                }

                OutputPins.Clear();
                foreach (var pin in outputPins) {
                    OutputPins.Add(pin);
                }
            }

            Inputs.Clear();
            foreach (var pair in value.Inputs.Enumerate()) {
                Inputs.Add(pair.Item.Value);
            }

            Properties.Clear();
            foreach (var pair in value.Properties) {
                Properties.Add(pair.Key, pair.Value);
            }
        }
    }

    [Property]
    [Sync]
    [TargetType(typeof(Node))]
    [Change(nameof(RecreateSerializableNode))]
    public SerializableType Type { get; set; } = null;
    private int? TypeLastHashCode = null;

    [Property]
    [Sync]
    [Change(nameof(RecreateSerializableNode))]
    public bool OverridePins { get; set; } = false;

    [Property]
    [ShowIf(nameof(OverridePins), true)]
    [Sync]
    [Change(nameof(RecreateSerializableNode))]
    public NetList<Pin> InputPins { get; set; } = [];

    [Property]
    [ShowIf(nameof(OverridePins), true)]
    [Sync]
    [Change(nameof(RecreateSerializableNode))]
    public NetList<Pin> OutputPins { get; set; } = [];

    [Property]
    [Sync]
    [Change(nameof(RecreateSerializableNode))]
    // [ObjectGenericControlWidget]
    [Hide]
    public NetList<object> Inputs { get; set; } = [];

    [Property]
    [Sync]
    [Change(nameof(RecreateSerializableNode))]
    [Hide]
    public NetDictionary<string, object> Properties { get; set; } = [];


    private Nodebox.Node _inner;

    [Property, ReadOnly]
    public Nodebox.Node Inner => _inner;
}