import LineBuilder from "../../../codegen/LineBuilder.js";

/**
 *
 * @param {number} id
 * @returns {string}
 */
function encode_node(id) {
    return `n${id}`;
}

/**
 *
 * @param {number} id
 * @returns {string}
 */
function encode_port(id) {
    return `p${id}`;
}

/**
 *
 * @param {NodeInstancePortReference} source
 * @returns {string}
 */
function encode_endpoint(source) {
    return `${encode_node(source.instance.id)}:${encode_port(source.port.id)}`;
}

/**
 * Creates a Graphviz diagram from a node graph
 * @see https://en.wikipedia.org/wiki/Graphviz
 * @see https://graphviz.org/
 * @see https://dreampuf.github.io/GraphvizOnline
 * @param {NodeGraph} graph
 * @returns {string}
 */
export function convert_node_graph_to_dot_string({ graph }) {
    // see https://stackoverflow.com/questions/7922960/block-diagram-layout-with-dot-graphviz

    const lb = new LineBuilder();

    lb.add('digraph G {');
    lb.indent();

    lb.add('graph [rankdir = LR];')
    lb.add('node[shape=record];')

    /**
     *
     * @param {NodeInstancePortReference[]} endpoints
     * @returns {string}
     */
    function portBlock(endpoints) {
        return `{${endpoints.map(e => `<${encode_port(e.port.id)}>${e.port.name}`).join("|")}}`;
    }

    // populate nodes
    const nodes = graph.getNodes();
    for (let i = 0; i < nodes.length; i++) {
        const node = nodes[i];

        const inputs = portBlock(node.inEndpoints);
        const outputs = portBlock(node.outEndpoints);

        lb.add(`${encode_node(node.id)}[label="{ ${inputs}|${node.description.name}/${node.id}|${outputs} }"];`)
    }

    // populate connections
    const connections = graph.getConnections();
    for (let i = 0; i < connections.length; i++) {
        const connection = connections[i];

        const source = connection.source;
        const target = connection.target;

        lb.add(`${encode_endpoint(source)} -> ${encode_endpoint(target)};`);
    }

    lb.dedent();
    lb.add('}');


    return lb.build();
}