Code/Util/PolymorphHelpers.cs
using Nodebox.Util.Math;

namespace Nodebox.Util;

public static class PolymorphHelpers {
    public static bool Operator(Node node, Type @base, Type specialized) {
        if (node.GetType() == @base) {
            return FromAny(node, specialized);
        } else if (TypeLibrary.GetType(node.GetType()).TargetType == specialized) {
            // return IfNone(node, @base);
            return false;
        } else {
            throw new Exception("wtf");
        }
    }

    public static bool IfNone(Node node, Type into) {
        foreach (var wire in node.AllWires) {
            var wireType = GetWireNonObjectType(wire);
            if (wireType != null) { return false; }
        }

        foreach (var pin in node.InputPinRefs.Concat(node.OutputPinRefs)) {
            pin.Type = typeof(object);
        }

        node.Polymorph(into);
        return true;
    }

    public static bool FromAny(Node node, Type intoGeneric) {
        foreach (var wire in node.AllWires) {
            var wireType = GetWireNonObjectType(wire);
            // Log.Info($"{wire} - {wireType}");

            if (wireType == null) { continue; }


            if (!Node.TryMakeGenericType(intoGeneric, [wireType], out var into)) {
                continue;
            }

            foreach (var pin in node.InputPinRefs.Concat(node.OutputPinRefs)) {
                pin.Type = wireType;
            }

            node.Polymorph(into);
            return true;
        }

        return false;
    }



    public static Type GetWireNonObjectType(Wire wire) =>
        (wire.SourceType == typeof(object) ? null : wire.SourceType) ??
        (wire.DestinationType == typeof(object) ? null : wire.DestinationType);
}