/*
 * Copyright 2026, Jaime Terrats.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
export function renderDiagram(data, format) {
    if (format === 'mermaid') {
        return renderMermaid(data);
    }
    return renderMaxGraphJson(data);
}
// ─── Mermaid rendering ──────────────────────────────────────────────────────
function renderMermaid(data) {
    switch (data.type) {
        case 'sequence':
            return renderSequenceMermaid(data);
        case 'class':
            return renderClassMermaid(data);
        case 'er':
            return renderErMermaid(data);
        case 'architecture':
        case 'flowchart':
        default:
            return renderFlowchartMermaid(data);
    }
}
function renderFlowchartMermaid(data) {
    const direction = data.direction ?? 'TB';
    const lines = [`flowchart ${direction}`];
    if (data.title) {
        lines.unshift(`---\ntitle: ${data.title}\n---`);
    }
    const groups = new Map();
    const ungrouped = [];
    for (const node of data.nodes) {
        if (node.group) {
            const list = groups.get(node.group) ?? [];
            list.push(node);
            groups.set(node.group, list);
        }
        else {
            ungrouped.push(node);
        }
    }
    for (const node of ungrouped) {
        lines.push(`  ${formatFlowchartNode(node)}`);
    }
    for (const [groupName, nodes] of groups) {
        lines.push(`  subgraph ${groupName}`);
        for (const node of nodes) {
            lines.push(`    ${formatFlowchartNode(node)}`);
        }
        lines.push('  end');
    }
    for (const edge of data.edges) {
        lines.push(`  ${formatFlowchartEdge(edge)}`);
    }
    return lines.join('\n');
}
function formatFlowchartNode(node) {
    const label = node.label;
    switch (node.shape) {
        case 'rounded':
            return `${node.id}(${label})`;
        case 'circle':
            return `${node.id}((${label}))`;
        case 'diamond':
            return `${node.id}{${label}}`;
        case 'hexagon':
            return `${node.id}{{${label}}}`;
        case 'stadium':
            return `${node.id}([${label}])`;
        case 'rectangle':
        default:
            return `${node.id}[${label}]`;
    }
}
function formatFlowchartEdge(edge) {
    const arrow = buildArrow(edge);
    const label = edge.label ? `|${edge.label}|` : '';
    return `${edge.from} ${arrow}${label} ${edge.to}`;
}
function buildArrow(edge) {
    const head = edge.arrowhead === 'none' ? '---' : '-->';
    switch (edge.style) {
        case 'dashed':
            return edge.arrowhead === 'none' ? '-.-' : '-.->';
        case 'dotted':
            return edge.arrowhead === 'none' ? '-.-' : '-.->';
        case 'thick':
            return edge.arrowhead === 'none' ? '===' : '==>';
        case 'solid':
        default:
            return head;
    }
}
function renderSequenceMermaid(data) {
    const lines = ['sequenceDiagram'];
    if (data.title) {
        lines.unshift(`---\ntitle: ${data.title}\n---`);
    }
    if (data.participants && data.participants.length > 0) {
        for (const p of data.participants) {
            lines.push(`  participant ${p}`);
        }
    }
    if (data.messages) {
        for (const msg of data.messages) {
            const arrow = sequenceArrow(msg.type);
            lines.push(`  ${msg.from}${arrow}${msg.to}: ${msg.label}`);
        }
    }
    return lines.join('\n');
}
function sequenceArrow(type) {
    switch (type) {
        case 'async':
            return '-)';
        case 'reply':
            return '-->>)';
        case 'sync':
        default:
            return '->>';
    }
}
function renderClassMermaid(data) {
    const lines = ['classDiagram'];
    if (data.title) {
        lines.unshift(`---\ntitle: ${data.title}\n---`);
    }
    for (const node of data.nodes) {
        lines.push(`  class ${node.id} {`);
        lines.push(`    ${node.label}`);
        lines.push('  }');
    }
    for (const edge of data.edges) {
        const label = edge.label ? ` : ${edge.label}` : '';
        lines.push(`  ${edge.from} --> ${edge.to}${label}`);
    }
    return lines.join('\n');
}
function renderErMermaid(data) {
    const lines = ['erDiagram'];
    if (data.title) {
        lines.unshift(`---\ntitle: ${data.title}\n---`);
    }
    for (const edge of data.edges) {
        const label = edge.label ?? 'relates-to';
        lines.push(`  ${edge.from} ||--o{ ${edge.to} : "${label}"`);
    }
    return lines.join('\n');
}
// ─── maxGraph JSON rendering ────────────────────────────────────────────────
function renderMaxGraphJson(data) {
    const json = buildMaxGraphJson(data);
    return JSON.stringify(json, null, 2);
}
function buildMaxGraphJson(data) {
    const NODE_WIDTH = 120;
    const NODE_HEIGHT = 60;
    const H_SPACING = 180;
    const V_SPACING = 100;
    const isVertical = !data.direction || data.direction === 'TB' || data.direction === 'BT';
    const nodePositions = new Map();
    const nodes = data.nodes.map((node, index) => {
        const x = isVertical ? (index % 4) * H_SPACING : index * H_SPACING;
        const y = isVertical ? Math.floor(index / 4) * V_SPACING : (index % 3) * V_SPACING;
        nodePositions.set(node.id, { x, y });
        const mgNode = {
            id: node.id,
            value: node.label,
            x,
            y,
            width: NODE_WIDTH,
            height: NODE_HEIGHT,
        };
        if (node.style) {
            mgNode.style = node.style;
        }
        if (node.group) {
            mgNode.parent = node.group;
        }
        return mgNode;
    });
    const edges = data.edges.map((edge, index) => {
        const mgEdge = {
            id: `e${index}`,
            source: edge.from,
            target: edge.to,
        };
        if (edge.label) {
            mgEdge.value = edge.label;
        }
        if (edge.style) {
            mgEdge.style = edgeStyleToMaxGraph(edge.style);
        }
        return mgEdge;
    });
    return { nodes, edges };
}
function edgeStyleToMaxGraph(style) {
    switch (style) {
        case 'dashed':
            return 'dashed=1';
        case 'dotted':
            return 'dashed=1;dashPattern=1 2';
        case 'thick':
            return 'strokeWidth=3';
        default:
            return '';
    }
}
//# sourceMappingURL=diagram-renderer.js.map