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, { forwardRef, useRef } from 'react';
import { TreeView, StringTypeIcon, HashtagIcon, ClockIcon, QuestionCircleIcon, ChevronDownIcon, ChevronRightIcon, compareLabelFn, AccessPointIcon, PURE_FlatDataStoreIcon, PURE_DatabaseTableIcon, PURE_IngestIcon, PanelLoadingIndicator, } from '@finos/legend-art';
import { flowResult } from 'mobx';
import { AccessorExplorerTreeColumnNodeData, AccessorExplorerTreeDataProductNodeData, AccessorExplorerTreeIngestNodeData, AccessorExplorerTreeAccessPointNodeData, AccessorExplorerTreeAccessPointGroupNodeData, AccessorExplorerTreeDatasetNodeData, AccessorExplorerTreeHeaderNodeData, } from '../../stores/sql-playground/SqlPlaygroundAccessorExplorerState.js';
import { PRECISE_PRIMITIVE_TYPE, V1_PackageableType, PRIMITIVE_TYPE, V1_AccessPoint, extractElementNameFromPath, } from '@finos/legend-graph';
import { observer } from 'mobx-react-lite';
import { useApplicationStore } from '@finos/legend-application';
import { useDrag } from 'react-dnd';
const SQL_DROP_NODE_DND_TYPE = 'SQL_DROP_NODE_DND_TYPE';
const STRING_TYPE_NAMES = new Set([
    extractElementNameFromPath(PRECISE_PRIMITIVE_TYPE.VARCHAR),
]);
const NUMERIC_TYPE_NAMES = new Set([
    extractElementNameFromPath(PRECISE_PRIMITIVE_TYPE.BIG_INT),
    extractElementNameFromPath(PRECISE_PRIMITIVE_TYPE.DECIMAL),
    extractElementNameFromPath(PRECISE_PRIMITIVE_TYPE.DOUBLE),
    extractElementNameFromPath(PRECISE_PRIMITIVE_TYPE.FLOAT),
    extractElementNameFromPath(PRECISE_PRIMITIVE_TYPE.INT),
    extractElementNameFromPath(PRECISE_PRIMITIVE_TYPE.NUMERIC),
    extractElementNameFromPath(PRECISE_PRIMITIVE_TYPE.SMALL_INT),
    extractElementNameFromPath(PRECISE_PRIMITIVE_TYPE.TINY_INT),
    extractElementNameFromPath(PRECISE_PRIMITIVE_TYPE.U_BIG_INT),
]);
const DATE_TYPE_NAMES = new Set([
    extractElementNameFromPath(PRECISE_PRIMITIVE_TYPE.STRICTDATE),
    extractElementNameFromPath(PRECISE_PRIMITIVE_TYPE.STRICTTIME),
    extractElementNameFromPath(PRECISE_PRIMITIVE_TYPE.DATETIME),
    extractElementNameFromPath(PRECISE_PRIMITIVE_TYPE.TIMESTAMP),
    extractElementNameFromPath(PRIMITIVE_TYPE.STRICTDATE),
]);
export const renderColumnTypeIcon = (type) => {
    const rawType = type.genericType.rawType;
    if (rawType instanceof V1_PackageableType) {
        const typeName = extractElementNameFromPath(rawType.fullPath);
        if (STRING_TYPE_NAMES.has(typeName)) {
            return (_jsx(StringTypeIcon, { className: "relation-source-tree__icon relation-source-tree__icon__string" }));
        }
        if (NUMERIC_TYPE_NAMES.has(typeName)) {
            return (_jsx(HashtagIcon, { className: "relation-source-tree__icon relation-source-tree__icon__number" }));
        }
        if (DATE_TYPE_NAMES.has(typeName)) {
            return (_jsx(ClockIcon, { className: "relation-source-tree__icon relation-source-tree__icon__time" }));
        }
    }
    return (_jsx(QuestionCircleIcon, { className: "relation-source-tree__icon relation-source-tree__icon__unknown" }));
};
const getAccessorNodeIcon = (node) => {
    if (node instanceof AccessorExplorerTreeColumnNodeData) {
        return renderColumnTypeIcon(node.column);
    }
    if (node instanceof AccessorExplorerTreeDataProductNodeData) {
        return (_jsx("div", { className: "Accessor-schema-explorer__icon--schema", children: _jsx(AccessPointIcon, {}) }));
    }
    if (node instanceof AccessorExplorerTreeIngestNodeData) {
        return (_jsx("div", { className: "Accessor-schema-explorer__icon--schema", children: _jsx(PURE_IngestIcon, {}) }));
    }
    if (node instanceof AccessorExplorerTreeAccessPointGroupNodeData) {
        return (_jsx("div", { className: "Accessor-schema-explorer__icon--table", children: _jsx(PURE_FlatDataStoreIcon, {}) }));
    }
    if (node instanceof AccessorExplorerTreeAccessPointNodeData ||
        node instanceof AccessorExplorerTreeDatasetNodeData) {
        return (_jsx("div", { className: "Accessor-schema-explorer__icon--table", children: _jsx(PURE_DatabaseTableIcon, {}) }));
    }
    return null;
};
export const AccessorExplorerTreeNodeContainer = observer(forwardRef(function AccessorExplorerTreeNodeContainer(props, ref) {
    const { node, level, onNodeSelect, innerProps } = props;
    const { toggleCheckedNode } = innerProps;
    const isExpandable = Boolean(!node.childrenIds || node.childrenIds.length) &&
        !(node instanceof AccessorExplorerTreeColumnNodeData);
    const nodeExpandIcon = isExpandable ? (node.isOpen ? (_jsx(ChevronDownIcon, {})) : (_jsx(ChevronRightIcon, {}))) : (_jsx("div", {}));
    const nodeTypeIcon = getAccessorNodeIcon(node);
    const toggleExpandNode = () => {
        onNodeSelect?.(node);
        if (!isExpandable) {
            toggleCheckedNode(node);
        }
    };
    return (_jsxs("div", { className: `tree-view__node__container Accessor-schema-explorer__node__container Accessor-schema-explorer__node__container--level-${Math.min(level, 6)}`, ref: ref, onClick: toggleExpandNode, children: [_jsx("div", { className: "tree-view__node__icon Accessor-schema-explorer__node__icon__group", children: _jsx("div", { className: "Accessor-schema-explorer__expand-icon", children: nodeExpandIcon }) }), nodeTypeIcon && (_jsx("div", { className: "Accessor-schema-explorer__type-icon", children: nodeTypeIcon })), _jsx("div", { className: "tree-view__node__label Accessor-schema-explorer__node__label", children: node.label })] }));
}));
export const SQLAccessorExplorer = observer((props) => {
    const { treeData, accessorExplorerState, treeNodeContainerComponent } = props;
    const applicationStore = useApplicationStore();
    const onNodeSelect = (node) => {
        flowResult(accessorExplorerState.onNodeSelect(node, treeData)).catch(applicationStore.alertUnhandledError);
    };
    const getChildNodes = (node) => accessorExplorerState
        .getChildNodes(node, treeData)
        ?.sort(compareLabelFn) ?? [];
    const isPartiallySelected = (node) => {
        if (node instanceof AccessorExplorerTreeDataProductNodeData &&
            !node.isChecked) {
            return (accessorExplorerState
                .getChildNodes(node, treeData)
                ?.some((childNode) => childNode.isChecked) ?? false);
        }
        return false;
    };
    const toggleCheckedNode = (node) => accessorExplorerState.toggleCheckedNode(node, treeData);
    return (_jsx(TreeView, { className: "Accessor-schema-explorer", components: {
            TreeNodeContainer: treeNodeContainerComponent ?? AccessorExplorerTreeNodeContainer,
        }, innerProps: {
            toggleCheckedNode,
            isPartiallySelected,
        }, treeData: treeData, onNodeSelect: onNodeSelect, getChildNodes: getChildNodes }));
});
const SQLPlaygroundAccessorExplorerTreeNodeContainer = observer((props) => {
    const { node } = props;
    const ref = useRef(null);
    const isDraggable = !(node instanceof AccessorExplorerTreeHeaderNodeData) &&
        !(node instanceof AccessorExplorerTreeAccessPointGroupNodeData);
    const dragText = node instanceof AccessorExplorerTreeColumnNodeData
        ? node.owner instanceof V1_AccessPoint
            ? `${node.parentId}.${node.label}`
            : `${node.owner.name}.${node.label}`
        : node instanceof AccessorExplorerTreeAccessPointNodeData
            ? `${node.dataProductPath}.${node.accessPoint.id}`
            : node instanceof AccessorExplorerTreeDatasetNodeData
                ? `${node.parentId}.${node.dataset.name}`
                : node instanceof AccessorExplorerTreeDataProductNodeData
                    ? node.id
                    : node instanceof AccessorExplorerTreeIngestNodeData
                        ? node.id
                        : node.id;
    const [, dragConnector] = useDrag(() => ({
        type: SQL_DROP_NODE_DND_TYPE,
        item: {
            text: dragText,
        },
        canDrag: isDraggable,
    }), [node, isDraggable]);
    if (isDraggable) {
        dragConnector(ref);
    }
    return _jsx(AccessorExplorerTreeNodeContainer, { ...props, ref: ref });
});
export const SQLPlaygroundExplorer = observer((props) => {
    const { accessorExplorerState } = props;
    return (_jsxs("div", { className: "sql-playground__explorer", children: [_jsx(PanelLoadingIndicator, { isLoading: Boolean(accessorExplorerState.isGeneratingAccessor) }), accessorExplorerState.treeData && (_jsx(SQLAccessorExplorer, { treeData: accessorExplorerState.treeData, accessorExplorerState: accessorExplorerState, treeNodeContainerComponent: SQLPlaygroundAccessorExplorerTreeNodeContainer }))] }));
});
//# sourceMappingURL=SQLPlaygroundExplorer.js.map