import layout from '@api-client/graph/layout/layout.js';
import { LayoutWeight, WorkspaceLayout } from './WorkspaceLayout.js';
export class DataModelLayout extends WorkspaceLayout {
    layout(model) {
        const { entities } = model;
        if (!entities.length) {
            return null;
        }
        this.readPositions = {};
        const g = this.initGraph();
        const selfEntities = entities.map((i) => i.key);
        const addedEntities = [];
        // parents first
        entities.forEach((entity) => {
            if (!this.ensureAddEntity(g, entity.key)) {
                return;
            }
            addedEntities.push(entity.key);
            entity.parents.forEach((id) => {
                if (selfEntities.includes(id) || addedEntities.includes(id) || g.node(id)) {
                    return;
                }
                this.ensureAddEntity(g, id);
                const config = {
                    minLen: 1,
                    weight: LayoutWeight.Parent,
                };
                g.setEdge(entity.key, id, config);
            });
            entity.associations.forEach((item) => {
                const targets = item.getTargets();
                if (!targets.length) {
                    return;
                }
                if (targets.length === 1) {
                    // classic association
                    const [target] = targets;
                    this.ensureAddEntity(g, target.key);
                    addedEntities.push(target.key);
                    // TODO: Union layout.
                }
            });
        });
        // once all entities are set we can add edges
        entities.forEach((entity) => {
            entity.associations.forEach((item) => {
                const targets = item.getTargets();
                if (!targets.length) {
                    return;
                }
                if (targets.length === 1) {
                    // classic association
                    const [target] = targets;
                    const isSelf = target === entity;
                    const config = {
                        minLen: 2,
                        weight: isSelf ? LayoutWeight.Self : LayoutWeight.Internal,
                    };
                    g.setEdge(entity.key, target.key, config);
                }
                else {
                    // TODO: Union layout.
                }
            });
        });
        layout(g);
        const nodes = [];
        g.nodes().forEach((id) => {
            const def = g.node(id);
            if (!def) {
                return;
            }
            const result = { ...def };
            result.x -= Math.round(result.width / 2);
            result.y -= Math.round(result.height / 2);
            nodes.push({
                id,
                node: result,
            });
        });
        return {
            graph: g,
            nodes,
        };
    }
    addEntityNode(graph, key, rect) {
        const { width, height } = rect;
        graph.setNode(key, {
            width,
            height,
        });
    }
    ensureAddEntity(graph, entityKey) {
        if (graph.node(entityKey)) {
            return false;
        }
        const position = this.readDimensions(entityKey);
        if (!position) {
            return false;
        }
        this.addEntityNode(graph, entityKey, position);
        return true;
    }
}
//# sourceMappingURL=DataModelLayout.js.map