import { Graph } from "../../../core/graph/v2/Graph.js";
import { ResourceAccessKind } from "../../../core/model/ResourceAccessKind.js";
import { EdgeDirectionType } from "../../../core/graph/Edge.js";

/**
 *
 * @param {number} system_count
 * @param {System[]} systems
 * @return {Graph}
 */
export function computeSystemComponentDependencyGraph(system_count, systems) {
    const dependency_graph = new Graph();

    for (let i = 0; i < system_count; i++) {
        const system = systems[i];

        const components = system.referenced_components;
        const component_count = components.length;

        // ensure that all components are registered
        for (let j = 0; j < component_count; j++) {
            const component = components[j];

            dependency_graph.addNode(component)
        }

        for (let j = 0; j < component_count; j++) {
            const component_a = components[j];

            const access_a = system.getAccessForComponent(component_a);

            if ((access_a & (ResourceAccessKind.Write | ResourceAccessKind.Create)) !== 0) {
                // writing resource, create dependency on read resources


                for (let k = 0; k < component_count; k++) {

                    if (j === k) {
                        // skip self
                        continue;
                    }

                    const component_b = components[k];

                    const access_b = system.getAccessForComponent(component_b);

                    if ((access_b & ResourceAccessKind.Read) !== 0) {
                        // read access

                        if (dependency_graph.getAnyDirectedEdge(component_a, component_b) === undefined) {

                            dependency_graph.createEdge(component_a, component_b, EdgeDirectionType.Forward);

                        }

                    }
                }

            }

        }

    }


    // console.log("DEPENDENCY_GRAPH:", convertGraphToDotString({
    //     graph: dependency_graph, nodeToDot: (node) => `[label="${node.typeName}"]`
    // }));

    return dependency_graph;
}
