using System;
using NodePipeline.Abstractions.Models;

namespace NodePipeline.Abstractions.Interfaces.Nodes;

/// <summary>
///     For implementation use <see cref="NodeField{T}" />
/// </summary>
public interface INodeField<T>
{
    /// <summary>
    ///     Node field name
    /// </summary>
    string Name { get; }

    /// <summary>
    ///     Description
    /// </summary>
    string? Description { get; }

    /// <summary>
    ///     Node field code (with node id)
    /// </summary>
    string Code { get; }

    /// <summary>
    ///     Node field value
    /// </summary>
    T Value { get; set; }

    /// <summary>
    ///     Node field direction
    ///     <para>
    ///         Port directions: <c>Input</c>, <c>Output</c>
    ///         <br />
    ///         Parameter: <c>Parameter</c>
    ///     </para>
    /// </summary>
    FieldDirection Direction { get; }

    /// <summary>
    ///     Method for connect two nodes directly
    /// </summary>
    /// <param name="outputPort">output port <c>Disallows null</c></param>
    void BindStatic(INodeField<T> outputPort);

    /// <summary>
    ///     Method for runtime binding
    /// </summary>
    /// <param name="getter">getter function – connection between two nodes <c>Disallows null</c></param>
    /// <param name="setter">setter action <c>Allows null</c></param>
    void BindRuntime(Func<T> getter, Action<T> setter);
}

public enum FieldDirection
{
    /// <summary>
    ///     Node field is port with direction <c>INPUT</c>
    /// </summary>
    Input,

    /// <summary>
    ///     Node field is port with direction <c>OUTPUT</c>
    /// </summary>
    Output,

    /// <summary>
    ///     Node field is <c>PARAMETER</c>
    /// </summary>
    Parameter
}