Code/Core/PinRef.cs
namespace Nodebox;

public /*ref*/ struct PinRef : IValid, IMeta {
    public PinRef(Node node, Flow flow, PinIndex index) {
        Node = node;
        Flow = flow;
        Index = index;
    }

    public Node Node { get; private set; }
    public Flow Flow { get; private set; }
    public PinIndex Index { get; private set; }
    public readonly string Name {
        get => IsValid ? Pin.Name : null;
        set => Node.ReplacePin(Flow, Index, Pin.WithName(value));
    }
    public readonly string Description {
        get => IsValid ? Pin.Description : null;
        set => Node.ReplacePin(Flow, Index, Pin.WithDescription(value));
    }
    public readonly bool HideInput {
        get => IsValid && Pin.HideInput;
        set => Node.ReplacePin(Flow, Index, Pin.WithHideInput(value));
    }
    public readonly Type Type {
        get => Pin.Type;
        set => Node.ReplacePin(Flow, Index, Pin.WithType(value));
    }

    public readonly Dictionary<string, object> Meta => Pin.Meta;
    public readonly Pin Pin {
        get {
            Assert();
            return Node.GetPin(Flow, Index);
        }
    }

    public readonly object Value => Node?.GetInputValueOrNull(Index);
    public readonly IReadOnlySet<Wire> Wires => Node?.GetWires(Flow)?.ElementAtOrDefault(Index);

    public readonly bool IsValid => Node.IsValid() && Node.HasPin(Flow, Index);

    private readonly void Assert() {
        if (!IsValid) {
            throw new Exception($"Dereferencing an invalid {nameof(PinRef)}");
        }
    }

    public override readonly string ToString() => $"{Name ?? "Anonymous"} at {Node}.{Flow}[{Index}]";
}


// public /*ref*/ struct PinRef<T> : IValid {
//     public PinRef(Node node, Flow flow, PinIndex index) {
//         Node = node;
//         Flow = flow;
//         Index = index;
//     }

//     public Node Node { get; private set; }
//     public Flow Flow { get; private set; }
//     public PinIndex Index { get; private set; }
//     public readonly Pin Pin {
//         get {
//             Assert();
//             return Node.GetPin(Flow, Index);
//         }
//     }
//     public readonly Type Type {
//         get {
//             Assert();
//             return typeof(T);
//         }
//     }

//     public readonly bool IsValid => Node.IsValid() && Node.HasPin(Flow, Index) && typeof(T) == Pin.Type;

//     private readonly void Assert() {
//         if (!IsValid) {
//             throw new Exception($"Dereferencing an invalid {nameof(PinRef<>)}<{nameof(T)}>");
//         }
//     }
// }