import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/**
 * Copyright (c) 2020-present, Goldman Sachs
 *
 * 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.
 */
import React, { useEffect } from 'react';
import { clsx, Dialog, Modal, ModalBody, ModalFooter, ModalFooterButton, ModalHeader, PanelContent, } from '@finos/legend-art';
import { observer } from 'mobx-react-lite';
import { Background, Controls, MiniMap, Position, ReactFlow, ReactFlowProvider, } from 'reactflow';
import { LINEAGE_VIEW_MODE, } from '../../stores/lineage/LineageState.js';
import { PropertyOwnerNode, } from '@finos/legend-graph';
import { PropertyOwnerNode as PropertyOwnerNodeComponent, } from './PropertyOwnerNode.js';
function autoLayoutNodesAndEdges(nodes, edges, xSpacing = 220, ySpacing = 120, areaHeight = 800) {
    // Build in-degree map
    const nodeIds = nodes.map((n) => n.id);
    const inDegree = {};
    nodeIds.forEach((id) => {
        inDegree[id] = 0;
    });
    edges.forEach((e) => {
        inDegree[e.target] = (inDegree[e.target] ?? 0) + 1;
    });
    // BFS to assign levels
    const levels = {};
    const queue = [];
    nodeIds.forEach((id) => {
        if (inDegree[id] === 0) {
            levels[id] = 0;
            queue.push(id);
        }
    });
    while (queue.length > 0) {
        const current = queue.shift();
        if (current === undefined) {
            continue; // should never happen, but safe fallback
        }
        const currentLevel = levels[current] ?? 0;
        edges.forEach((e) => {
            if (e.source === current) {
                const targetLevel = levels[e.target] ?? -1;
                if (targetLevel < currentLevel + 1) {
                    levels[e.target] = currentLevel + 1;
                    queue.push(e.target);
                }
            }
        });
    }
    // Group nodes by level
    const levelNodes = {};
    Object.entries(levels).forEach(([id, lvl]) => {
        if (!levelNodes[lvl]) {
            levelNodes[lvl] = [];
        }
        levelNodes[lvl].push(id);
    });
    // Position nodes
    const positions = {};
    const maxLevel = Object.values(levels).length
        ? Math.max(...Object.values(levels))
        : 0;
    for (let lvl = 0; lvl <= maxLevel; lvl++) {
        const ids = levelNodes[lvl] ?? [];
        const totalHeight = (ids.length - 1) * ySpacing;
        const startY = (areaHeight - totalHeight) / 2;
        ids.forEach((id, idx) => {
            positions[id] = {
                x: 80 + lvl * xSpacing,
                y: startY + idx * ySpacing,
            };
        });
    }
    // Fallback for disconnected nodes
    nodeIds.forEach((id, idx) => {
        if (!positions[id]) {
            positions[id] = {
                x: 80,
                y: 80 + idx * ySpacing,
            };
        }
    });
    return positions;
}
function getLayoutBounds(positions) {
    const xs = Object.values(positions).map((p) => p.x);
    const ys = Object.values(positions).map((p) => p.y);
    if (!xs.length || !ys.length) {
        return { width: 800, height: 600 };
    }
    const minX = Math.min(...xs);
    const maxX = Math.max(...xs);
    const minY = Math.min(...ys);
    const maxY = Math.max(...ys);
    // Add some padding
    return {
        width: Math.max(400, maxX - minX + 200),
        height: Math.max(300, maxY - minY + 200),
    };
}
const convertGraphToFlow = (graph) => {
    if (!graph?.nodes.length) {
        // Handle missing or empty graph
        return {
            nodes: [
                {
                    id: 'no-lineage',
                    data: { label: 'No Lineage Generated' },
                    position: { x: 350, y: 300 },
                    type: 'default',
                    style: {
                        backgroundColor: '#f5f5f5',
                        border: '1px solid #ccc',
                        borderRadius: '5px',
                        padding: '10px',
                        width: 200,
                    },
                },
            ],
            edges: [],
            bounds: { width: 800, height: 600 },
        };
    }
    const nodeList = graph.nodes.map((node) => ({
        id: node.data.id,
        label: node.data.text,
    }));
    const edgeList = graph.edges.map((edge) => ({
        source: edge.data.source.data.id,
        target: edge.data.target.data.id,
    }));
    const positions = autoLayoutNodesAndEdges(nodeList, edgeList);
    const bounds = getLayoutBounds(positions);
    // For class and database lineage, all nodes should have edges starting from right side
    const nodes = nodeList.map((node) => ({
        id: node.id,
        data: { label: node.label },
        position: positions[node.id] ?? { x: 0, y: 0 },
        type: 'default',
        sourcePosition: Position.Right,
        targetPosition: Position.Left,
    }));
    const edges = edgeList.map((edge, idx) => ({
        id: `${edge.source}-${edge.target}-${idx}`,
        source: edge.source,
        target: edge.target,
        type: 'smoothstep',
        // No explicit sourceHandle or targetHandle needed as we set sourcePosition and targetPosition on nodes
    }));
    return { nodes, edges, bounds };
};
const convertReportLineageToFlow = (reportLineage) => {
    if (!reportLineage?.columns.length) {
        // Handle missing or empty report lineage
        return {
            nodes: [
                {
                    id: 'no-report-lineage',
                    data: { label: 'No Lineage Generated' },
                    position: { x: 350, y: 300 },
                    type: 'default',
                    style: {
                        backgroundColor: '#f5f5f5',
                        border: '1px solid #ccc',
                        borderRadius: '5px',
                        padding: '10px',
                        width: 200,
                    },
                },
            ],
            edges: [],
            bounds: { width: 800, height: 600 },
        };
    }
    const nodes = [];
    const edges = [];
    // Layout constants
    const ySpacing = 70;
    const leftX = 100;
    const rightX = 500;
    const startY = 100;
    const columnWidth = 180;
    const tableWidth = 220;
    const headerHeight = 40;
    // Create report columns container
    const reportContainerId = 'report_columns_container';
    const reportContainerHeight = reportLineage.columns.length * ySpacing + headerHeight;
    nodes.push({
        id: reportContainerId,
        data: { label: 'Report Columns' },
        position: { x: leftX, y: startY },
        style: {
            width: columnWidth,
            height: reportContainerHeight,
            backgroundColor: '#eaf6ff',
            border: '2px solid #0073e6',
            borderRadius: '8px',
            padding: '10px',
            textAlign: 'center',
            fontWeight: 'bold',
        },
        type: 'default',
    });
    // Report columns inside the container
    reportLineage.columns.forEach((col, idx) => {
        const nodeId = `report_col_${col.name}`;
        nodes.push({
            id: nodeId,
            data: { label: col.name },
            position: { x: 10, y: headerHeight + idx * ySpacing },
            parentId: reportContainerId,
            extent: 'parent',
            style: {
                width: columnWidth - 20,
                backgroundColor: '#f0f7ff',
                border: '1px solid #0073e6',
                borderRadius: '5px',
                padding: '8px',
                zIndex: 10,
            },
            type: 'default',
            sourcePosition: Position.Right, // All report columns should have edges leaving from the right
            targetPosition: Position.Left,
        });
    });
    // Collect all unique owner/column pairs
    const tables = new Map();
    reportLineage.columns.forEach((col) => {
        col.columns.forEach((childCol) => {
            const ownerObj = childCol.column.owner;
            const ownerKey = `${ownerObj.schema.database.package}.${ownerObj.schema.database.name}.${ownerObj.schema.name}`;
            const columnName = childCol.column.name;
            if (!tables.has(ownerKey)) {
                tables.set(ownerKey, {
                    owner: ownerObj,
                    columns: [],
                });
            }
            const tableInfo = tables.get(ownerKey);
            if (!tableInfo) {
                return;
            }
            if (!tableInfo.columns.includes(columnName)) {
                tableInfo.columns.push(columnName);
            }
        });
    });
    // Place tables and their columns
    let currentY = startY;
    const tableColumnPositions = new Map();
    tables.forEach(({ owner, columns }, ownerKey) => {
        const tableId = `table_${ownerKey.replace(/[^a-zA-Z0-9]/g, '_')}`;
        const tableHeight = headerHeight + columns.length * ySpacing;
        // Table container node
        nodes.push({
            id: tableId,
            data: { label: owner.name },
            position: { x: rightX, y: currentY },
            style: {
                width: tableWidth,
                height: tableHeight,
                backgroundColor: '#f5f5f5',
                border: '2px solid #555',
                borderRadius: '5px',
                padding: '10px 0 0 0',
                fontWeight: 'bold',
            },
            type: 'default',
        });
        // Column nodes within table
        columns.forEach((column, colIdx) => {
            const columnId = `${tableId}_column_${column}`;
            const columnY = colIdx * ySpacing;
            tableColumnPositions.set(columnId, { x: 10, y: headerHeight + columnY });
            nodes.push({
                id: columnId,
                data: { label: column },
                position: { x: 10, y: headerHeight + columnY },
                parentId: tableId,
                extent: 'parent',
                style: {
                    width: tableWidth - 20,
                    backgroundColor: '#fff',
                    border: '1px solid #ccc',
                    borderRadius: '3px',
                    padding: '8px',
                    fontSize: '12px',
                    zIndex: 10,
                },
                type: 'default',
                sourcePosition: Position.Right,
                targetPosition: Position.Left, // All target columns should accept edges on the left
            });
        });
        currentY += tableHeight + 50; // Add spacing between tables
    });
    // Create edges between report columns and table columns
    reportLineage.columns.forEach((col) => {
        const sourceId = `report_col_${col.name}`;
        col.columns.forEach((childCol) => {
            const ownerObj = childCol.column.owner;
            const ownerKey = `${ownerObj.schema.database.package}.${ownerObj.schema.database.name}.${ownerObj.schema.name}`;
            const columnName = childCol.column.name;
            const tableId = `table_${ownerKey.replace(/[^a-zA-Z0-9]/g, '_')}`;
            const targetId = `${tableId}_column_${columnName}`;
            edges.push({
                id: `${sourceId}-${targetId}`,
                source: sourceId,
                target: targetId,
                type: 'default',
                style: { strokeWidth: 1.5 },
            });
        });
    });
    // Determine total height needed
    const totalHeight = Math.max(startY + reportContainerHeight + 100, currentY);
    return {
        nodes,
        edges,
        bounds: {
            width: rightX + tableWidth + 100,
            height: totalHeight,
        },
    };
};
const convertPropertyLineageToFlow = (propertyLineage, selectedSourcePropertiesMap) => {
    if (!propertyLineage?.propertyOwner.length) {
        return {
            nodes: [
                {
                    id: 'no-property-lineage',
                    data: { label: 'No Property Lineage Generated' },
                    position: { x: 350, y: 300 },
                    type: 'default',
                    style: {
                        backgroundColor: '#f5f5f5',
                        border: '1px solid #ccc',
                        borderRadius: '5px',
                        padding: '10px',
                        width: 200,
                    },
                },
            ],
            edges: [],
            bounds: { width: 800, height: 600 },
        };
    }
    const nodeList = propertyLineage.propertyOwner.map((node) => ({
        id: node.id,
        label: node.name,
        isPropertyOwner: node instanceof PropertyOwnerNode,
        node: node,
    }));
    const edgeList = propertyLineage.ownerLink.map((link) => ({
        source: link.source,
        target: link.target,
    }));
    const nodeIds = new Set(nodeList.map((n) => n.id));
    const validEdgeList = edgeList.filter((edge) => {
        return !(!nodeIds.has(edge.source) || !nodeIds.has(edge.target));
    });
    const nodeDimensions = new Map();
    nodeList.forEach((nodeItem) => {
        const isPropertyOwner = nodeItem.isPropertyOwner;
        const highlightedProperties = selectedSourcePropertiesMap?.get(nodeItem.id);
        const hasHighlightedProperties = (highlightedProperties?.size ?? 0) > 0;
        let nodeWidth = 220;
        let nodeHeight = isPropertyOwner ? 80 : 60;
        if (hasHighlightedProperties && isPropertyOwner) {
            const propertyCount = Math.min(highlightedProperties?.size ?? 0, 20);
            // Header (50px) + properties (32px each including margins) + container padding (20px)
            const propertiesHeight = propertyCount * 32; // 28px min-height + 4px margin
            nodeHeight = 50 + propertiesHeight + 20;
            nodeHeight = Math.max(nodeHeight, 160);
            nodeHeight = Math.min(nodeHeight, 800);
            nodeWidth = 340;
        }
        nodeDimensions.set(nodeItem.id, { width: nodeWidth, height: nodeHeight });
    });
    const maxHeight = Math.max(...Array.from(nodeDimensions.values()).map((d) => d.height));
    const dynamicYSpacing = Math.max(220, maxHeight + 100);
    const dynamicXSpacing = 380;
    const positions = autoLayoutNodesAndEdges(nodeList, validEdgeList, dynamicXSpacing, dynamicYSpacing);
    const bounds = getLayoutBounds(positions);
    const nodes = nodeList.map((nodeItem) => {
        const isPropertyOwner = nodeItem.isPropertyOwner;
        const highlightedProperties = selectedSourcePropertiesMap?.get(nodeItem.id);
        let allProperties = [];
        if (isPropertyOwner && nodeItem.node instanceof PropertyOwnerNode) {
            const properties = nodeItem.node.properties;
            // Handle the case where properties is empty or not an array
            if (Array.isArray(properties) && properties.length > 0) {
                allProperties = properties.map((prop) => ({
                    name: prop.name,
                    dataType: prop.dataType,
                    propertyType: prop.propertyType,
                }));
            }
            else {
                allProperties = [];
            }
        }
        const dimensions = nodeDimensions.get(nodeItem.id) ?? {
            width: 220,
            height: 80,
        };
        const nodeData = {
            label: nodeItem.label,
            isPropertyOwner: isPropertyOwner,
            highlightedProperties: highlightedProperties,
            allProperties: allProperties,
        };
        return {
            id: nodeItem.id,
            data: nodeData,
            position: positions[nodeItem.id] ?? { x: 0, y: 0 },
            type: isPropertyOwner ? 'propertyOwner' : 'default',
            sourcePosition: Position.Right,
            targetPosition: Position.Left,
            style: {
                width: dimensions.width,
                height: dimensions.height,
                background: 'transparent',
                border: 'none',
                padding: 0,
                margin: 0,
            },
            width: dimensions.width,
            height: dimensions.height,
        };
    });
    const edges = validEdgeList.map((edge, idx) => ({
        id: `${edge.source}-${edge.target}-${idx}`,
        source: edge.source,
        target: edge.target,
        type: 'smoothstep',
        style: { strokeWidth: 2, stroke: '#1976d2' },
    }));
    const expandedBounds = {
        width: Math.max(bounds.width, 1200),
        height: Math.max(bounds.height, 800),
    };
    return { nodes, edges, bounds: expandedBounds };
};
const collectSourceOwnerProperties = (property, map, visited = new Set(), depth = 0) => {
    if (depth > 50) {
        return;
    }
    if (!Array.isArray(property.sourceProperties) ||
        property.sourceProperties.length === 0) {
        return;
    }
    const propertyKey = `${property.ownerID}-${property.name}`;
    if (visited.has(propertyKey)) {
        return;
    }
    visited.add(propertyKey);
    try {
        property.sourceProperties.forEach((sourceProp) => {
            if (!map.has(sourceProp.ownerID)) {
                map.set(sourceProp.ownerID, new Set());
            }
            const sourceSet = map.get(sourceProp.ownerID);
            if (sourceSet) {
                sourceSet.add(sourceProp.name);
            }
            collectSourceOwnerProperties(sourceProp, map, visited, depth + 1);
        });
    }
    catch {
        return;
    }
    finally {
        visited.delete(propertyKey);
    }
};
const findRelevantEdges = (highlightedNodeIds, allEdges) => {
    const relevantEdgeIds = new Set();
    allEdges.forEach((edge) => {
        if (highlightedNodeIds.has(edge.source) &&
            highlightedNodeIds.has(edge.target)) {
            relevantEdgeIds.add(edge.id);
        }
    });
    return relevantEdgeIds;
};
const PROPERTY_LINEAGE_NODE_TYPES = {
    propertyOwner: PropertyOwnerNodeComponent,
};
const PropertyOwnerPanel = observer((props) => {
    const { lineageState, selectedNodeId } = props;
    const propertyLineage = lineageState.lineageData?.propertyLineage;
    if (!selectedNodeId || !propertyLineage) {
        return (_jsxs("div", { className: "property-lineage__panel", children: [_jsx("div", { className: "property-lineage__panel-header", children: _jsx("h3", { children: "Properties" }) }), _jsx("div", { className: "property-lineage__panel-content", children: _jsx("p", { children: "Select a node with properties to view details" }) })] }));
    }
    const selectedNode = propertyLineage.propertyOwner.find((node) => node.id === selectedNodeId);
    const isPropertyOwner = selectedNode instanceof PropertyOwnerNode;
    if (!isPropertyOwner) {
        return (_jsxs("div", { className: "property-lineage__panel", children: [_jsx("div", { className: "property-lineage__panel-header", children: _jsx("h3", { children: "Properties" }) }), _jsx("div", { className: "property-lineage__panel-content", children: _jsx("p", { children: "Selected node has no properties" }) })] }));
    }
    const propertyOwnerNode = selectedNode;
    const handlePropertyClick = (property) => {
        const propertyKey = `${property.ownerID}-${property.name}`;
        const currentSelection = lineageState.selectedProperty;
        lineageState.setSelectedProperty(currentSelection === propertyKey ? undefined : propertyKey);
        if (currentSelection === propertyKey) {
            lineageState.setSelectedSourcePropertiesMap(undefined);
        }
        else {
            const map = new Map();
            collectSourceOwnerProperties(property, map, new Set(), 0);
            lineageState.setSelectedSourcePropertiesMap(map);
        }
    };
    // Ensure properties is always an array
    const properties = Array.isArray(propertyOwnerNode.properties)
        ? propertyOwnerNode.properties
        : [];
    let highlightedSourceProps = undefined;
    if (lineageState.selectedSourcePropertiesMap?.has(propertyOwnerNode.id)) {
        highlightedSourceProps = lineageState.selectedSourcePropertiesMap.get(propertyOwnerNode.id);
    }
    return (_jsxs("div", { className: "property-lineage__panel", children: [_jsxs("div", { className: "property-lineage__panel-header", children: [_jsx("h3", { children: propertyOwnerNode.name }), _jsxs("span", { className: "property-lineage__panel-subtitle", children: [properties.length, " properties"] })] }), _jsx("div", { className: "property-lineage__panel-content", children: properties.length === 0 ? (_jsx("p", { children: "No properties found" })) : (_jsx("div", { className: "property-lineage__properties-list", children: properties.map((property) => {
                        const propertyKey = `${property.ownerID}-${property.name}`;
                        const isSelected = lineageState.selectedProperty === propertyKey;
                        const isSourceHighlighted = highlightedSourceProps?.has(property.name);
                        return (_jsxs("div", { className: clsx('property-lineage__property-item', {
                                'property-lineage__property-item--selected': isSelected,
                                'property-lineage__property-item--source-highlighted': isSourceHighlighted,
                            }), onClick: () => handlePropertyClick(property), style: { cursor: 'pointer' }, children: [_jsx("div", { className: "property-lineage__property-name", children: property.name }), _jsxs("div", { className: "property-lineage__property-details", children: [_jsx("span", { className: "property-lineage__property-type", children: property.dataType ?? 'Unknown' }), _jsx("span", { className: "property-lineage__property-scope", children: property.propertyType })] }), property.scope && (_jsx("div", { className: "property-lineage__property-scope-detail", children: property.scope })), Array.isArray(property.sourceProperties) &&
                                    property.sourceProperties.length > 0 && (_jsxs("div", { className: "property-lineage__property-sources", children: [property.sourceProperties.length, " source properties"] }))] }, propertyKey));
                    }) })) })] }));
});
const PropertyLineageGraphViewer = observer((props) => {
    const { lineageState, nodes, edges } = props;
    const getHighlightMaps = () => {
        const highlightedNodeIds = new Set();
        const sourcePropertiesMap = lineageState.selectedSourcePropertiesMap ??
            new Map();
        if (!lineageState.selectedProperty ||
            !lineageState.selectedPropertyOwnerNode) {
            return { highlightedNodeIds, sourcePropertiesMap };
        }
        const propertyLineage = lineageState.lineageData?.propertyLineage;
        if (!propertyLineage) {
            return { highlightedNodeIds, sourcePropertiesMap };
        }
        const selectedNode = propertyLineage.propertyOwner.find((node) => node.id === lineageState.selectedPropertyOwnerNode);
        if (!(selectedNode instanceof PropertyOwnerNode)) {
            return { highlightedNodeIds, sourcePropertiesMap };
        }
        const [ownerID, propertyName] = lineageState.selectedProperty.split('-');
        const selectedProperty = selectedNode.properties.find((prop) => prop.ownerID === ownerID && prop.name === propertyName);
        if (selectedProperty) {
            highlightedNodeIds.add(selectedProperty.ownerID);
            for (const ownerId of sourcePropertiesMap.keys()) {
                highlightedNodeIds.add(ownerId);
            }
        }
        return { highlightedNodeIds, sourcePropertiesMap };
    };
    const { highlightedNodeIds, sourcePropertiesMap } = getHighlightMaps();
    const onNodeClick = (_event, node) => {
        if (node.data.isPropertyOwner) {
            lineageState.setSelectedPropertyOwnerNode(lineageState.selectedPropertyOwnerNode === node.id
                ? undefined
                : node.id);
            lineageState.setSelectedProperty(undefined);
            lineageState.setSelectedSourcePropertiesMap(undefined);
        }
    };
    const enhancedNodes = nodes.map((node) => {
        const isSelected = lineageState.selectedPropertyOwnerNode === node.id;
        // Remove unnecessary type annotation
        const isHighlighted = highlightedNodeIds.has(node.id);
        // Add type for updatedData to avoid unsafe assignment
        const updatedData = {
            ...node.data,
            isSelected,
            isHighlighted,
        };
        return {
            ...node,
            data: updatedData,
            style: {
                ...node.style,
                cursor: node.data.isPropertyOwner ? 'pointer' : 'default',
                background: node.type === 'propertyOwner'
                    ? 'transparent'
                    : node.style?.backgroundColor,
                border: node.type === 'propertyOwner'
                    ? 'none'
                    : isSelected
                        ? '3px solid #ff6b35'
                        : isHighlighted
                            ? '3px solid #4caf50'
                            : node.style?.border,
                zIndex: isSelected ? 1000 : isHighlighted ? 100 : 1,
            },
        };
    });
    const highlightedEdgeIds = findRelevantEdges(highlightedNodeIds, edges);
    const enhancedEdges = edges.map((edge) => {
        const isHighlighted = highlightedEdgeIds.has(edge.id);
        return {
            ...edge,
            style: {
                ...edge.style,
                strokeWidth: isHighlighted ? 4 : 2,
                stroke: isHighlighted ? '#4caf50' : '#1976d2',
                opacity: isHighlighted ? 1 : 0.6,
            },
        };
    });
    // DO NOT set selectedSourcePropertiesMap here as it causes infinite re-renders
    // The map is already set in handlePropertyClick
    return (_jsxs("div", { style: { height: '100%', width: '100%', display: 'flex' }, children: [_jsx("div", { style: { flex: 1, height: '100%' }, children: _jsx(ReactFlowProvider, { children: _jsxs(ReactFlow, { nodes: enhancedNodes, edges: enhancedEdges, nodeTypes: PROPERTY_LINEAGE_NODE_TYPES, defaultEdgeOptions: { type: 'default' }, defaultViewport: { x: 0, y: 0, zoom: 0.6 }, fitView: true, fitViewOptions: {
                            padding: 0.2,
                            minZoom: 0.3,
                            maxZoom: 1.5,
                        }, nodesDraggable: true, onNodeClick: onNodeClick, nodeExtent: [
                            [-1000, -1000],
                            [3000, 3000],
                        ], children: [_jsx(Background, {}), _jsx(MiniMap, {}), _jsx(Controls, {})] }, `${lineageState.selectedProperty}-${sourcePropertiesMap.size}`) }) }), lineageState.selectedPropertyOwnerNode && (_jsx("div", { style: { width: '350px', borderLeft: '1px solid #ccc' }, children: _jsx(PropertyOwnerPanel, { lineageState: lineageState, selectedNodeId: lineageState.selectedPropertyOwnerNode }) }))] }));
});
// Graph Viewer Component
const LineageGraphViewer = observer((props) => {
    const { nodes, edges } = props;
    return (_jsx("div", { style: { height: '100%', width: '100%' }, children: _jsx(ReactFlowProvider, { children: _jsx("div", { style: { width: '100%', height: '100%' }, children: _jsxs(ReactFlow, { nodes: nodes, edges: edges, defaultEdgeOptions: { type: 'default' }, defaultViewport: { x: 0, y: 0, zoom: 1.5 }, fitView: true, nodesDraggable: true, children: [_jsx(Background, {}), _jsx(MiniMap, {}), _jsx(Controls, {})] }) }) }) }));
});
const TAB_ORDER = [
    LINEAGE_VIEW_MODE.DATABASE_LINEAGE,
    LINEAGE_VIEW_MODE.PROPERTY_LINEAGE,
    LINEAGE_VIEW_MODE.CLASS_LINEAGE,
    LINEAGE_VIEW_MODE.REPORT_LINEAGE,
];
const TAB_LABELS = {
    [LINEAGE_VIEW_MODE.CLASS_LINEAGE]: 'Class Lineage',
    [LINEAGE_VIEW_MODE.DATABASE_LINEAGE]: 'Database Lineage',
    [LINEAGE_VIEW_MODE.REPORT_LINEAGE]: 'Report Lineage',
    [LINEAGE_VIEW_MODE.PROPERTY_LINEAGE]: 'Property Lineage',
};
const LineageTabSelector = observer((props) => {
    const { lineageState } = props;
    return (_jsx("div", { className: "viewer__header lineage-viewer__header--with-tabs", children: _jsx("div", { children: TAB_ORDER.map((tab) => (_jsx("div", { onClick: () => lineageState.setSelectedTab(tab), className: clsx('lineage-viewer__tab', {
                    'lineage-viewer__tab--active': tab === lineageState.selectedTab,
                }), children: TAB_LABELS[tab] }, tab))) }) }));
});
export const LineageViewerContent = observer((props) => {
    const { lineageState } = props;
    const selectedTab = lineageState.selectedTab;
    const lineageData = lineageState.lineageData;
    const classLineageFlow = convertGraphToFlow(lineageData?.classLineage);
    const databaseLineageFlow = convertGraphToFlow(lineageData?.databaseLineage);
    const reportLineageFlow = convertReportLineageToFlow(lineageData?.reportLineage);
    const propertyLineageFlow = convertPropertyLineageToFlow(lineageData?.propertyLineage, lineageState.selectedSourcePropertiesMap);
    return (_jsx("div", { className: "lineage-viewer", style: { height: '100%' }, children: _jsxs("div", { style: { height: '100%' }, children: [_jsx(LineageTabSelector, { lineageState: lineageState }), _jsxs(PanelContent, { children: [selectedTab === LINEAGE_VIEW_MODE.CLASS_LINEAGE && (_jsx(LineageGraphViewer, { nodes: classLineageFlow.nodes, edges: classLineageFlow.edges })), selectedTab === LINEAGE_VIEW_MODE.DATABASE_LINEAGE && (_jsx(LineageGraphViewer, { nodes: databaseLineageFlow.nodes, edges: databaseLineageFlow.edges })), selectedTab === LINEAGE_VIEW_MODE.REPORT_LINEAGE && (_jsx(LineageGraphViewer, { nodes: reportLineageFlow.nodes, edges: reportLineageFlow.edges })), selectedTab === LINEAGE_VIEW_MODE.PROPERTY_LINEAGE && (_jsx(PropertyLineageGraphViewer, { lineageState: lineageState, nodes: propertyLineageFlow.nodes, edges: propertyLineageFlow.edges }))] })] }) }));
});
export const LineageViewer = observer((props) => {
    const { lineageState } = props;
    const closeLineageViewer = () => {
        lineageState.setLineageData(undefined);
        lineageState.setSelectedTab(LINEAGE_VIEW_MODE.DATABASE_LINEAGE);
        lineageState.clearPropertySelections();
    };
    useEffect(() => {
        lineageState.setSelectedTab(LINEAGE_VIEW_MODE.DATABASE_LINEAGE);
    }, [lineageState]);
    if (!lineageState.lineageData) {
        return null;
    }
    const isDarkMode = !lineageState.applicationStore.layoutService
        .TEMPORARY__isLightColorThemeEnabled;
    return (_jsx(Dialog, { open: Boolean(lineageState.lineageData), onClose: closeLineageViewer, children: _jsxs(Modal, { className: "editor-modal", darkMode: isDarkMode, children: [_jsx(ModalHeader, { title: "Lineage Viewer" }), _jsx(ModalBody, { children: _jsx("div", { className: "lineage-viewer", style: { height: '100%' }, children: _jsx(LineageViewerContent, { lineageState: lineageState }) }) }), _jsx(ModalFooter, { className: "editor-modal__footer", children: _jsx(ModalFooterButton, { onClick: closeLineageViewer, text: "Close", type: "secondary" }) })] }) }));
});
//# sourceMappingURL=LineageViewer.js.map