Code/Core/Contexts/ExecutionContext/ExecutionContext.Check.cs
namespace Nodebox;

public partial class ExecutionContext {
    public virtual List<CheckException> Check(Graph graph) {
        var exceptions = new List<CheckException>();
        foreach (var wire in graph.GetAll<Wire>()) {
            try {
                CheckWire(graph, wire);
            } catch (CheckException exception) {
                exceptions.Add(exception);
            }
        }
        return exceptions;
    }

    protected void CheckWire(Graph graph, Wire wire) {
        CheckException.ThrowIf(
            graph.Contains<Node>(wire.Source),
            graph,
            wire,
            $"wire {nameof(wire.Source)} node is not in the provided graph"
        );

        CheckException.ThrowIf(
            graph.Contains<Node>(wire.Destination),
            graph,
            wire,
            $"wire {nameof(wire.Destination)} node is not in the provided graph"
        );

        CheckException.ThrowIf(
            !IsValidConnection(wire.SourcePin, wire.DestinationPin),
            graph,
            wire,
            $"wire {nameof(wire.Source)} pin type doesn't match {nameof(wire.Destination)} pin type"
        );
    }

    public virtual bool IsValidConnection(Pin src, Pin dst) {
        return src.Type == dst.Type;
    }

    public class CheckException(Graph graph, GraphElement element, string message) : Exception(message) {
        public Graph Graph { get; set; } = graph;
        public GraphElement Element { get; set; } = element;

        public static void ThrowIf(bool value, Graph graph, GraphElement element, string message = null) {
            if (value) {
                throw new CheckException(graph, element, message);
            }
        }
    }
}