import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } 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, { Fragment, useRef, useEffect, useState, forwardRef, } from 'react';
import { observer } from 'mobx-react-lite';
import { clsx, Dialog, MenuContent, MenuContentItem, MenuContentItemBlankIcon, MenuContentItemIcon, MenuContentItemLabel, ContextMenu, ControlledDropdownMenu, PanelLoadingIndicator, BlankPanelContent, TreeView, ChevronDownIcon, ChevronRightIcon, CompressIcon, FolderIcon, FolderOpenIcon, PlusIcon, LockIcon, ExclamationTriangleIcon, SearchIcon, FileImportIcon, SettingsEthernetIcon, MenuContentDivider, createFilter, CustomSelectorInput, LevelDownIcon, CaretDownIcon, PURE_ClassIcon, CodeIcon, } from '@finos/legend-art';
import { getElementIcon, getElementTypeIcon } from '../../ElementIconUtils.js';
import { getElementTypeLabel, CreateNewElementModal, } from './CreateNewElementModal.js';
import { useDrag } from 'react-dnd';
import { ElementDragSource } from '../../../stores/editor/utils/DnDUtils.js';
import { LEGEND_STUDIO_TEST_ID } from '../../../__lib__/LegendStudioTesting.js';
import { ACTIVITY_MODE, GRAPH_EDITOR_MODE, PANEL_MODE, } from '../../../stores/editor/EditorConfig.js';
import { getTreeChildNodes } from '../../../stores/editor/utils/PackageTreeUtils.js';
import { getFileSystemChildNodes, } from '../../../stores/editor/utils/FileSystemTreeUtils.js';
import { FileSystemTree } from '../editor-group/element-generation-editor/FileSystemViewer.js';
import { generateViewEntityRoute, generateViewProjectByGAVRoute, } from '../../../__lib__/LegendStudioNavigation.js';
import { guaranteeNonEmptyString, guaranteeNonNullable, guaranteeType, isNonNullable, toTitleCase, } from '@finos/legend-shared';
import { flowResult } from 'mobx';
import { useEditorStore } from '../EditorStoreProvider.js';
import { ELEMENT_PATH_DELIMITER, ROOT_PACKAGE_NAME, Package, isValidFullPath, isValidPath, isGeneratedElement, isSystemElement, isDependencyElement, isElementReadOnly, ConcreteFunctionDefinition, Class, isMainGraphElement, getFunctionSignature, getFunctionNameWithPath, getElementRootPackage, PackageableConnection, guaranteeRelationalDatabaseConnection, extractDependencyGACoordinateFromRootPackageName, Database, DEPENDENCY_ROOT_PACKAGE_PREFIX, Service, isRelationalDatabaseConnection, LegendSDLC, DataProduct, IngestDefinition, isAccessorDataProductOrIngestDefinition, } from '@finos/legend-graph';
import { ActionAlertActionType, ActionAlertType, useApplicationStore, } from '@finos/legend-application';
import { getPackageableElementOptionFormatter, } from '@finos/legend-lego/graph-editor';
import { LegendSQLPlaygroundModal } from '../LegendSQLPlaygroundModal.js';
import { PACKAGEABLE_ELEMENT_GROUP_BY_CATEGORY, PACKAGEABLE_ELEMENT_TYPE, } from '../../../stores/editor/utils/ModelClassifierUtils.js';
import { useLegendStudioApplicationStore } from '../../LegendStudioFrameworkProvider.js';
import { queryClass } from '../editor-group/uml-editor/ClassQueryBuilder.js';
import { createViewSDLCProjectHandler } from '../../../stores/editor/DependencyProjectViewerHelper.js';
import { MASTER_SNAPSHOT_ALIAS, SNAPSHOT_VERSION_ALIAS, } from '@finos/legend-server-depot';
import { CLASS_MOCK_DATA_GENERATION_FORMAT, createMockDataForClassWithFormat, } from '../../../stores/editor/utils/MockDataUtils.js';
import { CODE_EDITOR_LANGUAGE } from '@finos/legend-code-editor';
import { CodeEditor } from '@finos/legend-lego/code-editor';
import { DatabaseBuilderWizard } from '../editor-group/connection-editor/DatabaseBuilderWizard.js';
import { DatabaseModelBuilder } from '../editor-group/connection-editor/DatabaseModelBuilder.js';
import { queryService } from '../editor-group/service-editor/ServiceExecutionQueryEditor.js';
import { isElementSupportedByDataCube, openDataCube, } from '../../../stores/editor/data-cube/LegendStudioDataCubeHelper.js';
import { queryDataProduct } from '../editor-group/dataProduct/DataProductQueryBuilderHelper.js';
import { queryAccessorSource } from '../editor-group/accessor/AccessorQueryBuilderHelper.js';
const ElementRenamer = observer(() => {
    const editorStore = useEditorStore();
    const applicationStore = useApplicationStore();
    const explorerTreeState = editorStore.explorerTreeState;
    const element = explorerTreeState.elementToRename;
    const [path, setPath] = useState((element instanceof ConcreteFunctionDefinition
        ? getFunctionNameWithPath(element)
        : element?.path) ?? '');
    const [canRenameElement, setCanRenameElement] = useState(false);
    const [elementRenameValidationErrorMessage, setElementRenameValidationErrorMessage,] = useState('');
    const pathInputRef = useRef(null);
    const changePath = (event) => {
        const currentValue = event.target.value;
        setPath(currentValue);
        const isElementPathNonEmpty = currentValue !== '';
        const isNotTopLevelElement = element instanceof Package ||
            currentValue.includes(ELEMENT_PATH_DELIMITER);
        const isValidElementPath = (element instanceof Package && isValidPath(currentValue)) ||
            isValidFullPath(currentValue);
        let existingElement = editorStore.graphManagerState.graph.getNullableElement(currentValue, true);
        existingElement =
            existingElement instanceof Package
                ? isMainGraphElement(existingElement)
                    ? existingElement
                    : undefined
                : existingElement;
        const isElementUnique = !existingElement || existingElement === element;
        const errorMessage = !isElementPathNonEmpty
            ? `Element path cannot be empty`
            : !isNotTopLevelElement
                ? `Creating top level element is not allowed`
                : !isValidElementPath
                    ? `Element path is not valid`
                    : !isElementUnique
                        ? `Element of the same path already existed`
                        : '';
        setElementRenameValidationErrorMessage(errorMessage);
        setCanRenameElement(isElementPathNonEmpty &&
            isNotTopLevelElement &&
            isValidElementPath &&
            isElementUnique);
    };
    const rename = (event) => {
        event.preventDefault();
        if (element && canRenameElement) {
            explorerTreeState.setElementToRename(undefined);
            flowResult(editorStore.graphEditorMode.renameElement(element, element instanceof ConcreteFunctionDefinition
                ? path + getFunctionSignature(element)
                : path))
                .then(() => {
                setCanRenameElement(false);
                setElementRenameValidationErrorMessage('');
            })
                .catch(applicationStore.alertUnhandledError);
        }
    };
    const abort = () => {
        setCanRenameElement(false);
        setElementRenameValidationErrorMessage('');
        explorerTreeState.setElementToRename(undefined);
    };
    const onEnter = () => pathInputRef.current?.focus();
    useEffect(() => {
        if (element) {
            setPath(element instanceof ConcreteFunctionDefinition
                ? getFunctionNameWithPath(element)
                : element.path);
        }
    }, [element]);
    return (_jsx(Dialog, { open: Boolean(element), onClose: abort, slotProps: {
            transition: {
                onEnter: onEnter,
            },
            paper: {
                classes: { root: 'search-modal__inner-container' },
            },
        }, classes: { container: 'search-modal__container' }, children: _jsxs("form", { className: "modal modal--dark search-modal explorer__element-renamer", children: [_jsx("div", { className: "modal__title", children: "Rename Element" }), _jsxs("div", { className: "input-group", children: [_jsx("input", { className: "input-group__input input--dark explorer__element-renamer__input", ref: pathInputRef, value: path, placeholder: "Enter element path", onChange: changePath }), elementRenameValidationErrorMessage && (_jsx("div", { className: "input-group__error-message", children: elementRenameValidationErrorMessage }))] }), _jsxs("div", { className: "search-modal__actions", children: [_jsx("button", { type: "button", className: "btn btn--dark", onClick: abort, children: "Cancel" }), _jsx("button", { className: "btn btn--dark", disabled: !canRenameElement, onClick: rename, children: "Rename" })] })] }) }));
});
const GENERATION_DEFAULT_DEPTH = 100;
const GENERATION_DEFAULT_FORMAT = CLASS_MOCK_DATA_GENERATION_FORMAT.JSON;
const getMockDataEditorLanguage = (format) => {
    switch (format) {
        case CLASS_MOCK_DATA_GENERATION_FORMAT.JSON:
            return CODE_EDITOR_LANGUAGE.JSON;
        case CLASS_MOCK_DATA_GENERATION_FORMAT.XML:
            return CODE_EDITOR_LANGUAGE.XML;
        case CLASS_MOCK_DATA_GENERATION_FORMAT.YAML:
            return CODE_EDITOR_LANGUAGE.YAML;
        default:
            return CODE_EDITOR_LANGUAGE.TEXT;
    }
};
const SampleDataGenerator = observer(() => {
    const editorStore = useEditorStore();
    const applicationStore = editorStore.applicationStore;
    const explorerTreeState = editorStore.explorerTreeState;
    const selectedClass = explorerTreeState.classToGenerateSampleData;
    const [format, setFormat] = useState(GENERATION_DEFAULT_FORMAT);
    const [depth, setDepth] = useState(GENERATION_DEFAULT_DEPTH);
    const [resultText, setResultText] = useState('');
    const changeDepth = (event) => {
        setDepth(parseInt(event.target.value, 10));
    };
    // class
    const classSelectorRef = useRef(null);
    const elementFilterOption = createFilter({
        ignoreCase: true,
        ignoreAccents: false,
        stringify: (option) => option.data.value.path,
    });
    const classOptions = editorStore.graphManagerState.usableClasses.map((_class) => ({
        value: _class,
        label: _class.name,
    }));
    const selectedClassOption = selectedClass
        ? {
            value: selectedClass,
            label: selectedClass.name,
        }
        : null;
    const changeClass = (val) => {
        if (val.value === selectedClass) {
            return;
        }
        explorerTreeState.setClassToGenerateSampleData(val.value);
    };
    useEffect(() => {
        if (selectedClass) {
            setResultText(createMockDataForClassWithFormat(selectedClass, format, depth));
        }
    }, [selectedClass, format, depth]);
    const abort = () => {
        setFormat(GENERATION_DEFAULT_FORMAT);
        setDepth(GENERATION_DEFAULT_DEPTH);
        explorerTreeState.setClassToGenerateSampleData(undefined);
    };
    const regenerate = () => {
        if (selectedClass) {
            setResultText(createMockDataForClassWithFormat(selectedClass, format, depth));
        }
    };
    const onEnter = () => classSelectorRef.current?.focus();
    return (_jsx(Dialog, { open: Boolean(selectedClass), onClose: abort, slotProps: {
            transition: {
                onEnter: onEnter,
            },
            paper: {
                classes: { root: 'search-modal__inner-container' },
            },
        }, classes: { container: 'search-modal__container' }, children: _jsxs("div", { className: "modal modal--dark search-modal explorer__element-renamer", children: [_jsx("div", { className: "modal__title", children: "Generate Sample Data" }), _jsxs("div", { className: "sample-data-generator__controller", children: [_jsx("div", { className: "sample-data-generator__controller__icon", title: "class", children: _jsx(PURE_ClassIcon, {}) }), _jsx(CustomSelectorInput, { inputRef: classSelectorRef, className: "sample-data-generator__controller__class-selector", options: classOptions, onChange: changeClass, value: selectedClassOption, darkMode: !applicationStore.layoutService
                                .TEMPORARY__isLightColorThemeEnabled, filterOption: elementFilterOption, formatOptionLabel: getPackageableElementOptionFormatter({
                                darkMode: !applicationStore.layoutService
                                    .TEMPORARY__isLightColorThemeEnabled,
                            }) }), _jsx("div", { className: "sample-data-generator__controller__icon", title: "format", children: _jsx(CodeIcon, {}) }), _jsxs(ControlledDropdownMenu, { className: "sample-data-generator__controller__format-selector", title: "Choose Element Type...", content: _jsx(MenuContent, { className: "sample-data-generator__controller__format-selector__options", children: Object.values(CLASS_MOCK_DATA_GENERATION_FORMAT).map((val) => (_jsx(MenuContentItem, { className: "sample-data-generator__controller__format-selector__option", onClick: () => setFormat(val), children: val }, val))) }), children: [_jsx("div", { className: "sample-data-generator__controller__format-selector__label", children: format }), _jsx("div", { className: "sample-data-generator__controller__format-selector__dropdown-indicator", children: _jsx(CaretDownIcon, {}) })] }), _jsx("div", { className: "sample-data-generator__controller__icon", title: "depth", children: _jsx(LevelDownIcon, {}) }), _jsx("input", { className: "input input--dark sample-data-generator__controller__depth", value: depth, type: "number", onChange: changeDepth })] }), _jsx("div", { className: "sample-data-generator__result", children: _jsx(CodeEditor, { inputValue: resultText, isReadOnly: true, hideGutter: true, language: getMockDataEditorLanguage(format) }) }), _jsxs("div", { className: "search-modal__actions", children: [_jsx("button", { type: "button", className: "btn btn--dark", onClick: abort, children: "Cancel" }), _jsx("button", { className: "btn btn--dark", onClick: regenerate, children: "Regenerate" })] })] }) }));
});
const isRelationalDatabase = (val) => (val instanceof Database ? val : undefined);
const ExplorerContextMenu = observer(forwardRef(function ExplorerContextMenu(props, ref) {
    const { node, nodeIsImmutable } = props;
    const editorStore = useEditorStore();
    const applicationStore = useLegendStudioApplicationStore();
    const extraExplorerContextMenuItems = editorStore.pluginManager
        .getApplicationPlugins()
        .flatMap((plugin) => plugin.getExtraExplorerContextMenuItemRendererConfigurations?.() ??
        [])
        .map((config) => {
        const action = config.renderer(editorStore, node?.packageableElement);
        if (!action) {
            return null;
        }
        return _jsx(Fragment, { children: action }, config.key);
    })
        .filter(isNonNullable);
    const projectId = editorStore.sdlcState.currentProject?.projectId;
    const isReadOnly = editorStore.disableGraphEditing || Boolean(nodeIsImmutable);
    const isDependencyProjectElement = node && isDependencyElement(node.packageableElement);
    const _package = node
        ? node.packageableElement instanceof Package
            ? node.packageableElement
            : undefined
        : editorStore.graphManagerState.graph.root;
    const elementTypesWithCategory = _package === editorStore.graphManagerState.graph.root
        ? new Map([
            [
                PACKAGEABLE_ELEMENT_GROUP_BY_CATEGORY.MODEL,
                [PACKAGEABLE_ELEMENT_TYPE.PACKAGE],
            ],
        ])
        : editorStore.supportedElementTypesWithCategory;
    // actions
    const buildQuery = editorStore.applicationStore.guardUnhandledError(async () => {
        if (node?.packageableElement instanceof Class) {
            await queryClass(node.packageableElement, editorStore);
        }
    });
    const buildDataProductQuery = editorStore.applicationStore.guardUnhandledError(async () => {
        if (node?.packageableElement instanceof DataProduct) {
            await queryDataProduct(node.packageableElement, editorStore);
        }
    });
    const openLegendSqlPlayground = () => {
        if (node?.packageableElement &&
            isAccessorDataProductOrIngestDefinition(node.packageableElement)) {
            editorStore.legendSQLStudioPlaygroundState.open(node.packageableElement);
        }
    };
    const buildServiceQuery = editorStore.applicationStore.guardUnhandledError(async () => {
        if (node?.packageableElement instanceof Service) {
            await queryService(node.packageableElement, editorStore);
        }
    });
    const buildAccessorQuery = editorStore.applicationStore.guardUnhandledError(async () => {
        if (node?.packageableElement instanceof IngestDefinition ||
            node?.packageableElement instanceof Database) {
            await queryAccessorSource(node.packageableElement, editorStore);
        }
    });
    const openCubeViewer = editorStore.applicationStore.guardUnhandledError(async () => {
        if (node?.packageableElement) {
            await openDataCube(node.packageableElement, editorStore);
        }
    });
    const generateSampleData = editorStore.applicationStore.guardUnhandledError(async () => {
        if (node?.packageableElement instanceof Class) {
            editorStore.explorerTreeState.setClassToGenerateSampleData(node.packageableElement);
        }
    });
    const buildDatabase = editorStore.applicationStore.guardUnhandledError(async () => {
        if (isRelationalDatabaseConnection(node?.packageableElement)) {
            editorStore.explorerTreeState.buildDatabase(guaranteeRelationalDatabaseConnection(node?.packageableElement), editorStore.isInViewerMode);
        }
    });
    const generateModelsFromDatabaseSpecification = editorStore.applicationStore.guardUnhandledError(async () => {
        const database = isRelationalDatabase(node?.packageableElement);
        if (database) {
            if (database.joins.length === 0) {
                applicationStore.alertService.setActionAlertInfo({
                    message: 'You are attempting to build models but have defined no joins. Are you sure you wish to proceed?',
                    type: ActionAlertType.CAUTION,
                    actions: [
                        {
                            label: 'Proceed',
                            type: ActionAlertActionType.PROCEED_WITH_CAUTION,
                            handler: () => {
                                editorStore.explorerTreeState.buildDatabaseModels(database, editorStore.disableGraphEditing);
                            },
                        },
                        {
                            label: 'Abort',
                            type: ActionAlertActionType.PROCEED,
                            default: true,
                        },
                    ],
                });
            }
            else {
                editorStore.explorerTreeState.buildDatabaseModels(database, editorStore.disableGraphEditing);
            }
        }
    });
    const openSQLPlayground = () => {
        if (isRelationalDatabaseConnection(node?.packageableElement)) {
            editorStore.panelGroupDisplayState.open();
            editorStore.setActivePanelMode(PANEL_MODE.SQL_PLAYGROUND);
            editorStore.studioSqlPlaygroundState.setConnection(guaranteeType(node?.packageableElement, PackageableConnection));
        }
    };
    const removeElement = () => {
        if (node) {
            flowResult(editorStore.graphEditorMode.deleteElement(node.packageableElement)).catch(applicationStore.alertUnhandledError);
        }
    };
    const renameElement = () => {
        if (node) {
            editorStore.explorerTreeState.setElementToRename(node.packageableElement);
        }
    };
    const openElementInViewerMode = () => {
        if (node && projectId) {
            applicationStore.navigationService.navigator.visitAddress(applicationStore.navigationService.navigator.generateAddress(generateViewEntityRoute(projectId, node.packageableElement.path)));
        }
    };
    const copyPath = () => {
        if (node) {
            applicationStore.clipboardService
                .copyTextToClipboard(node.packageableElement.path)
                .then(() => applicationStore.notificationService.notifySuccess('Copied element path to clipboard'))
                .catch(applicationStore.alertUnhandledError);
        }
    };
    const copyWorkspaceElementLink = () => {
        if (node) {
            const dependency = editorStore.projectConfigurationEditorState.projectConfiguration?.projectDependencies.find((dep) => DEPENDENCY_ROOT_PACKAGE_PREFIX + dep.projectId ===
                getElementRootPackage(node.packageableElement).name);
            if (dependency) {
                applicationStore.clipboardService
                    .copyTextToClipboard(applicationStore.navigationService.navigator.generateAddress(editorStore.editorMode.generateDependencyElementLink(node.packageableElement.path, dependency)))
                    .then(() => applicationStore.notificationService.notifySuccess('Copied workspace element link to clipboard'))
                    .catch(applicationStore.alertUnhandledError);
            }
            else {
                applicationStore.clipboardService
                    .copyTextToClipboard(applicationStore.navigationService.navigator.generateAddress(editorStore.editorMode.generateElementLink(node.packageableElement.path)))
                    .then(() => applicationStore.notificationService.notifySuccess('Copied workspace element link to clipboard'))
                    .catch(applicationStore.alertUnhandledError);
            }
        }
    };
    const copySDLCProjectLink = () => {
        if (node) {
            const dependency = editorStore.projectConfigurationEditorState.projectConfiguration?.projectDependencies.find((dep) => DEPENDENCY_ROOT_PACKAGE_PREFIX + dep.projectId ===
                getElementRootPackage(node.packageableElement).name);
            if (dependency) {
                applicationStore.clipboardService
                    .copyTextToClipboard(applicationStore.navigationService.navigator.generateAddress(generateViewProjectByGAVRoute(guaranteeNonNullable(dependency.groupId), guaranteeNonNullable(dependency.artifactId), dependency.versionId === MASTER_SNAPSHOT_ALIAS
                    ? SNAPSHOT_VERSION_ALIAS
                    : dependency.versionId)))
                    .then(() => applicationStore.notificationService.notifySuccess('Copied SDLC project link to clipboard'))
                    .catch(applicationStore.alertUnhandledError);
            }
        }
    };
    const createNewElement = (type) => () => editorStore.newElementState.openModal(type, _package);
    const isDependencyProjectRoot = () => node?.packageableElement instanceof Package &&
        editorStore.graphManagerState.graph.dependencyManager.roots.includes(node.packageableElement);
    const viewProject = () => {
        if (node?.packageableElement.name) {
            const projectOrigin = editorStore.graphManagerState.graph.dependencyManager.projectDependencyModelsIndex.get(node.packageableElement.name.substring(DEPENDENCY_ROOT_PACKAGE_PREFIX.length))?.origin;
            if (projectOrigin instanceof LegendSDLC) {
                applicationStore.navigationService.navigator.visitAddress(applicationStore.navigationService.navigator.generateAddress(generateViewProjectByGAVRoute(guaranteeNonNullable(projectOrigin.groupId), guaranteeNonNullable(projectOrigin.artifactId), projectOrigin.versionId === MASTER_SNAPSHOT_ALIAS
                    ? SNAPSHOT_VERSION_ALIAS
                    : projectOrigin.versionId)));
            }
        }
    };
    const viewSDLCProject = () => {
        if (node?.packageableElement.name) {
            const sdlcProjectOrigin = editorStore.graphManagerState.graph.dependencyManager.projectDependencyModelsIndex.get(node.packageableElement.name.substring(DEPENDENCY_ROOT_PACKAGE_PREFIX.length))?.origin;
            if (sdlcProjectOrigin instanceof LegendSDLC) {
                createViewSDLCProjectHandler(applicationStore, editorStore.depotServerClient)(guaranteeNonEmptyString(sdlcProjectOrigin.groupId), guaranteeNonEmptyString(sdlcProjectOrigin.artifactId)).catch(applicationStore.alertUnhandledError);
            }
        }
    };
    if (isDependencyProjectRoot()) {
        return (_jsxs(MenuContent, { "data-testid": LEGEND_STUDIO_TEST_ID.EXPLORER_CONTEXT_MENU, children: [_jsx(MenuContentItem, { onClick: viewProject, children: _jsx(MenuContentItemLabel, { children: "View Project" }) }), node && (_jsx(MenuContentItem, { onClick: viewSDLCProject, children: _jsx(MenuContentItemLabel, { children: "View SDLC Project" }) }))] }));
    }
    if (_package && !isReadOnly) {
        return (_jsxs(MenuContent, { "data-testid": LEGEND_STUDIO_TEST_ID.EXPLORER_CONTEXT_MENU, children: [Array.from(elementTypesWithCategory.entries()).map((entry) => (_jsxs("div", { className: "editor-group__view-mode__option__group editor-group__view-mode__option__group--native", children: [_jsx("div", { className: "editor-group__view-mode__option__group__name", children: entry[0] }), _jsx("div", { className: "editor-group__view-mode__option__group__options editor-group__view-mode__option__group__options--center", children: entry[1].map((type) => (_jsxs(MenuContentItem, { onClick: createNewElement(type), children: [_jsx(MenuContentItemIcon, { children: getElementTypeIcon(type, editorStore) }), _jsx(MenuContentItemLabel, { children: toTitleCase(getElementTypeLabel(editorStore, type)) })] }, type))) })] }, entry[0]))), node && (_jsxs(_Fragment, { children: [_jsxs(MenuContentItem, { onClick: renameElement, children: [_jsx(MenuContentItemBlankIcon, {}), _jsx(MenuContentItemLabel, { children: "Rename" })] }), _jsxs(MenuContentItem, { onClick: removeElement, children: [_jsx(MenuContentItemBlankIcon, {}), _jsx(MenuContentItemLabel, { children: "Remove" })] })] }))] }));
    }
    if (!node) {
        return null;
    }
    return (_jsxs(MenuContent, { "data-testid": LEGEND_STUDIO_TEST_ID.EXPLORER_CONTEXT_MENU, children: [node.packageableElement instanceof DataProduct && (_jsxs(_Fragment, { children: [_jsx(MenuContentItem, { onClick: buildDataProductQuery, children: "Query..." }), _jsx(MenuContentItem, { onClick: openLegendSqlPlayground, children: "Run SQL..." }), _jsx(MenuContentDivider, {})] })), node.packageableElement instanceof Class && (_jsxs(_Fragment, { children: [_jsx(MenuContentItem, { onClick: buildQuery, children: "Query..." }), _jsx(MenuContentItem, { onClick: generateSampleData, children: "Generate Sample Data..." }), _jsx(MenuContentDivider, {})] })), node.packageableElement instanceof Service && (_jsx(_Fragment, { children: _jsx(MenuContentItem, { onClick: buildServiceQuery, children: "Query..." }) })), node.packageableElement instanceof IngestDefinition && (_jsxs(_Fragment, { children: [_jsx(MenuContentItem, { onClick: buildAccessorQuery, children: "Query..." }), _jsx(MenuContentItem, { onClick: openLegendSqlPlayground, children: "Run SQL..." }), _jsx(MenuContentDivider, {})] })), isElementSupportedByDataCube(node.packageableElement) && (_jsxs(_Fragment, { children: [_jsx(MenuContentItem, { onClick: openCubeViewer, children: "Data Cube (BETA)..." }), _jsx(MenuContentDivider, {})] })), isRelationalDatabaseConnection(node.packageableElement) && (_jsxs(_Fragment, { children: [_jsx(MenuContentItem, { onClick: openSQLPlayground, children: "Execute SQL..." }), _jsx(MenuContentItem, { onClick: buildDatabase, children: "Build Database..." }), _jsx(MenuContentDivider, {})] })), isRelationalDatabase(node.packageableElement) && (_jsxs(_Fragment, { children: [_jsx(MenuContentItem, { onClick: buildAccessorQuery, children: "Query..." }), _jsx(MenuContentItem, { onClick: generateModelsFromDatabaseSpecification, children: "Build Models" }), _jsx(MenuContentDivider, {})] })), extraExplorerContextMenuItems, Boolean(extraExplorerContextMenuItems.length) && (_jsx(MenuContentDivider, {})), !isReadOnly && (_jsxs(_Fragment, { children: [_jsx(MenuContentItem, { onClick: renameElement, children: "Rename" }), _jsx(MenuContentItem, { onClick: removeElement, children: "Remove" })] })), _jsx(MenuContentDivider, {}), !editorStore.isInViewerMode && !isDependencyProjectElement && (_jsx(MenuContentItem, { onClick: openElementInViewerMode, children: "View in Project" })), _jsx(MenuContentItem, { onClick: copyPath, children: "Copy Path" }), _jsx(MenuContentItem, { onClick: copyWorkspaceElementLink, children: "Copy Link" }), isDependencyProjectElement && (_jsx(MenuContentItem, { onClick: copySDLCProjectLink, children: "Copy SDLC Project Link" }))] }));
}));
const ProjectConfig = observer(() => {
    const editorStore = useEditorStore();
    const openConfigurationEditor = () => editorStore.tabManagerState.openTab(editorStore.projectConfigurationEditorState);
    const isSelected = editorStore.tabManagerState.currentTab ===
        editorStore.projectConfigurationEditorState &&
        // if we select non-element like packages, we need to deselect project configuration
        // so maybe a good TODO is to move this to explorer tree state
        !editorStore.explorerTreeState.selectedNode;
    return (_jsxs("div", { className: clsx('tree-view__node__container explorer__package-tree__node__container explorer__floating-item', { 'explorer__package-tree__node__container--selected': isSelected }), onClick: openConfigurationEditor, children: [_jsx("div", { className: "tree-view__node__icon explorer__package-tree__node__icon", children: _jsx("div", { className: "explorer__package-tree__node__icon__type explorer__config__icon", children: _jsx("div", { children: _jsx(SettingsEthernetIcon, {}) }) }) }), _jsx("button", { className: "tree-view__node__label explorer__package-tree__node__label", tabIndex: -1, title: "Project configuration", children: "config" })] }));
});
const PackageTreeNodeContainer = observer((props) => {
    const { node, level, stepPaddingInRem, onNodeSelect, innerProps } = props;
    const editorStore = useEditorStore();
    const [isSelectedFromContextMenu, setIsSelectedFromContextMenu] = useState(false);
    const { disableContextMenu, isContextImmutable } = innerProps;
    const [, dragConnector] = useDrag(() => ({
        type: node.dndType,
        item: new ElementDragSource(node),
    }), [node]);
    const ref = useRef(null);
    dragConnector(ref);
    const isPackage = node.packageableElement instanceof Package;
    const expandIcon = !isPackage ? (_jsx("div", {})) : node.isOpen ? (_jsx(ChevronDownIcon, {})) : (_jsx(ChevronRightIcon, {}));
    const iconPackageColor = isGeneratedElement(node.packageableElement)
        ? 'color--generated'
        : isSystemElement(node.packageableElement)
            ? 'color--system'
            : isDependencyElement(node.packageableElement)
                ? 'color--dependency'
                : '';
    const nodeIcon = isPackage ? (node.isOpen ? (_jsx("div", { className: iconPackageColor, children: _jsx(FolderOpenIcon, {}) })) : (_jsx("div", { className: iconPackageColor, children: _jsx(FolderIcon, {}) }))) : (getElementIcon(node.packageableElement, editorStore));
    const selectNode = () => onNodeSelect?.(node);
    const onContextMenuOpen = () => setIsSelectedFromContextMenu(true);
    const onContextMenuClose = () => setIsSelectedFromContextMenu(false);
    return (_jsx(ContextMenu, { content: _jsx(ExplorerContextMenu, { node: node, nodeIsImmutable: isContextImmutable }), disabled: disableContextMenu, menuProps: { elevation: 7 }, onOpen: onContextMenuOpen, onClose: onContextMenuClose, children: _jsxs("div", { className: clsx('tree-view__node__container explorer__package-tree__node__container', {
                'menu__trigger--on-menu-open': !node.isSelected && isSelectedFromContextMenu,
            }, {
                'explorer__package-tree__node__container--selected': node.isSelected,
            }), ref: ref, onClick: selectNode, style: {
                paddingLeft: `${level * (stepPaddingInRem ?? 1)}rem`,
                display: 'flex',
            }, children: [_jsxs("div", { className: "tree-view__node__icon explorer__package-tree__node__icon", children: [_jsx("div", { className: "explorer__package-tree__node__icon__expand", children: expandIcon }), _jsx("div", { className: "explorer__package-tree__node__icon__type", children: nodeIcon })] }), _jsx("button", { className: "tree-view__node__label explorer__package-tree__node__label", tabIndex: -1, title: node.packageableElement.path, children: extractDependencyGACoordinateFromRootPackageName(node.label) ??
                        node.label })] }) }));
});
const ExplorerDropdownMenu = observer(() => {
    const editorStore = useEditorStore();
    const _package = editorStore.explorerTreeState.getSelectedNodePackage();
    const createNewElement = (type) => () => editorStore.newElementState.openModal(type, _package);
    const elementTypesWithCategory = _package === editorStore.graphManagerState.graph.root
        ? new Map([
            [
                PACKAGEABLE_ELEMENT_GROUP_BY_CATEGORY.MODEL,
                [PACKAGEABLE_ELEMENT_TYPE.PACKAGE],
            ],
        ])
        : editorStore.supportedElementTypesWithCategory;
    return (_jsx(MenuContent, { "data-testid": LEGEND_STUDIO_TEST_ID.EXPLORER_CONTEXT_MENU, children: Array.from(elementTypesWithCategory.entries()).map((entry) => (_jsxs("div", { className: "editor-group__view-mode__option__group editor-group__view-mode__option__group--native", children: [_jsx("div", { className: "editor-group__view-mode__option__group__name", children: entry[0] }), _jsx("div", { className: "editor-group__view-mode__option__group__options editor-group__view-mode__option__group__options--center", children: entry[1].map((type) => (_jsxs(MenuContentItem, { onClick: createNewElement(type), children: [_jsx(MenuContentItemIcon, { children: getElementTypeIcon(type, editorStore) }), _jsx(MenuContentItemLabel, { children: toTitleCase(getElementTypeLabel(editorStore, type)) })] }, type))) })] }, entry[0]))) }));
});
const ExplorerTrees = observer(() => {
    const editorStore = useEditorStore();
    const { disableGraphEditing } = editorStore;
    const isInGrammarTextMode = editorStore.graphEditorMode.mode === GRAPH_EDITOR_MODE.GRAMMAR_TEXT;
    const openModelImport = () => editorStore.tabManagerState.openTab(editorStore.modelImporterState);
    const graph = editorStore.graphManagerState.graph;
    // Explorer tree
    const treeData = editorStore.explorerTreeState.getTreeData();
    const selectedTreeNode = editorStore.explorerTreeState.selectedNode;
    const onNodeSelect = (node) => editorStore.explorerTreeState.onTreeNodeSelect(node, treeData);
    const getChildNodes = (node) => getTreeChildNodes(editorStore, node, treeData);
    const deselectTreeNode = () => {
        if (selectedTreeNode) {
            selectedTreeNode.isSelected = false;
            editorStore.explorerTreeState.setTreeData({ ...treeData });
        }
        editorStore.explorerTreeState.setSelectedNode(undefined);
    };
    // Generated Tree
    const generationTreeData = editorStore.explorerTreeState.getTreeData(ROOT_PACKAGE_NAME.MODEL_GENERATION);
    const onGenerationTreeNodeSelect = (node) => editorStore.explorerTreeState.onTreeNodeSelect(node, generationTreeData, ROOT_PACKAGE_NAME.MODEL_GENERATION);
    const getGenerationTreeChildNodes = (node) => getTreeChildNodes(editorStore, node, generationTreeData);
    // Generated Files Tree
    const generationFileTreeData = editorStore.explorerTreeState.getArtifactsGenerationTreeData();
    const onGenerationFileTreeNodeSelect = (node) => editorStore.graphState.graphGenerationState.onTreeNodeSelect(node, generationFileTreeData);
    const getGenerationFileTreeChildNodes = (node) => getFileSystemChildNodes(node, generationFileTreeData);
    // System Tree
    const systemTreeData = editorStore.explorerTreeState.getTreeData(ROOT_PACKAGE_NAME.SYSTEM);
    const onSystemTreeNodeSelect = (node) => editorStore.explorerTreeState.onTreeNodeSelect(node, systemTreeData, ROOT_PACKAGE_NAME.SYSTEM);
    const getSystemTreeChildNodes = (node) => getTreeChildNodes(editorStore, node, systemTreeData);
    // Dependency Tree
    const dependencyTreeData = editorStore.explorerTreeState.getTreeData(ROOT_PACKAGE_NAME.PROJECT_DEPENDENCY_ROOT);
    const onDependencyTreeSelect = (node) => editorStore.explorerTreeState.onTreeNodeSelect(node, dependencyTreeData, ROOT_PACKAGE_NAME.PROJECT_DEPENDENCY_ROOT);
    const getDependencyTreeChildNodes = (node) => getTreeChildNodes(editorStore, node, dependencyTreeData, true);
    const showPackageTrees = treeData.nodes.size || graph.dependencyManager.hasDependencies;
    return (_jsxs(ContextMenu, { className: "explorer__content", disabled: isInGrammarTextMode || disableGraphEditing, content: _jsx(ExplorerContextMenu, {}), menuProps: { elevation: 7 }, children: [_jsxs("div", { "data-testid": LEGEND_STUDIO_TEST_ID.EXPLORER_TREES, children: [editorStore.explorerTreeState.buildState.hasCompleted &&
                        showPackageTrees && (_jsxs(_Fragment, { children: [_jsx(TreeView, { components: {
                                    TreeNodeContainer: PackageTreeNodeContainer,
                                }, treeData: treeData, onNodeSelect: onNodeSelect, getChildNodes: getChildNodes, innerProps: {
                                    disableContextMenu: isInGrammarTextMode,
                                } }), _jsx(ElementRenamer, {}), _jsx(SampleDataGenerator, {}), editorStore.explorerTreeState.databaseBuilderState && (_jsx(DatabaseBuilderWizard, { databaseBuilderState: editorStore.explorerTreeState.databaseBuilderState, isReadOnly: false })), editorStore.explorerTreeState.databaseModelBuilderState && (_jsx(DatabaseModelBuilder, { databaseModelBuilderState: editorStore.explorerTreeState.databaseModelBuilderState, isReadOnly: false })), editorStore.projectConfigurationEditorState
                                .projectConfiguration && _jsx(ProjectConfig, {}), Boolean(editorStore.graphManagerState.systemModel.allOwnElements.length) && (_jsx(TreeView, { components: {
                                    TreeNodeContainer: PackageTreeNodeContainer,
                                }, treeData: systemTreeData, onNodeSelect: onSystemTreeNodeSelect, getChildNodes: getSystemTreeChildNodes, innerProps: {
                                    disableContextMenu: true,
                                } })), graph.dependencyManager.hasDependencies && (_jsx(TreeView, { components: {
                                    TreeNodeContainer: PackageTreeNodeContainer,
                                }, treeData: dependencyTreeData, onNodeSelect: onDependencyTreeSelect, getChildNodes: getDependencyTreeChildNodes, innerProps: {
                                    disableContextMenu: isInGrammarTextMode,
                                    isContextImmutable: true,
                                } })), Boolean(graph.generationModel.allOwnElements.length) && (_jsx(TreeView, { components: {
                                    TreeNodeContainer: PackageTreeNodeContainer,
                                }, treeData: generationTreeData, onNodeSelect: onGenerationTreeNodeSelect, getChildNodes: getGenerationTreeChildNodes, innerProps: {
                                    disableContextMenu: isInGrammarTextMode,
                                    isContextImmutable: true,
                                } })), _jsx("div", {}), Boolean(editorStore.graphState.graphGenerationState.rootFileDirectory
                                .children.length) && (_jsxs(_Fragment, { children: [_jsx("div", { className: "explorer__content__separator" }), _jsx(FileSystemTree, { selectedNode: editorStore.explorerTreeState.selectedNode, directoryTreeData: generationFileTreeData, onNodeSelect: onGenerationFileTreeNodeSelect, getFileElementTreeChildNodes: getGenerationFileTreeChildNodes })] }))] })), editorStore.explorerTreeState.buildState.hasCompleted &&
                        !showPackageTrees && (_jsxs("div", { className: "explorer__content--empty", children: [_jsx("div", { className: "explorer__content--empty__text", children: "Your workspace is empty, you can add elements or load existing model/entites for quick adding" }), _jsx("button", { className: "btn--dark explorer__content--empty__btn", onClick: openModelImport, children: "Open Model Importer" })] }))] }), _jsx("div", { className: "explorer__deselector", onClick: deselectTreeNode })] }));
});
const ProjectExplorerActionPanel = observer((props) => {
    const { disabled } = props;
    const editorStore = useEditorStore();
    const isInGrammarMode = editorStore.graphEditorMode.mode === GRAPH_EDITOR_MODE.GRAMMAR_TEXT;
    const showSearchModal = () => editorStore.setShowSearchElementCommand(true);
    // Explorer tree
    const selectedTreeNode = editorStore.explorerTreeState.selectedNode;
    const collapseTree = () => {
        const treeData = editorStore.explorerTreeState.getTreeData();
        treeData.nodes.forEach((node) => {
            node.isOpen = false;
        });
        editorStore.explorerTreeState.setTreeData({ ...treeData });
    };
    const showModelImporter = () => editorStore.tabManagerState.openTab(editorStore.modelImporterState);
    const openConfigurationEditor = () => editorStore.tabManagerState.openTab(editorStore.projectConfigurationEditorState);
    return (_jsxs("div", { className: "panel__header__actions", children: [_jsx("button", { className: "panel__header__action", disabled: disabled, title: "Open Model Importer (F2)", onClick: showModelImporter, children: _jsx(FileImportIcon, {}) }), editorStore.editorMode.supportSdlcOperations && (_jsx("button", { className: "panel__header__action panel__header__action--config", disabled: disabled, title: "Project Configuration Panel", onClick: openConfigurationEditor, children: _jsx(SettingsEthernetIcon, {}) })), !editorStore.disableGraphEditing && (_jsx(ControlledDropdownMenu, { className: "panel__header__action", title: "New Element... (Ctrl + Shift + N)", disabled: disabled ||
                    isInGrammarMode ||
                    (selectedTreeNode &&
                        isElementReadOnly(selectedTreeNode.packageableElement)), content: _jsx(ExplorerDropdownMenu, {}), menuProps: {
                    anchorOrigin: { vertical: 'bottom', horizontal: 'left' },
                    transformOrigin: { vertical: 'top', horizontal: 'left' },
                    elevation: 7,
                }, children: _jsx(PlusIcon, {}) })), _jsx("button", { className: "panel__header__action", disabled: disabled, onClick: collapseTree, tabIndex: -1, title: "Collapse All", children: _jsx(CompressIcon, {}) }), _jsx("button", { className: "panel__header__action", disabled: disabled, tabIndex: -1, onClick: showSearchModal, title: "Open Element... (Ctrl + P)", children: _jsx(SearchIcon, {}) })] }));
});
export const Explorer = observer(() => {
    const editorStore = useEditorStore();
    const applicationStore = useApplicationStore();
    const sdlcState = editorStore.sdlcState;
    const isLoading = ((!editorStore.explorerTreeState.buildState.hasCompleted &&
        editorStore.graphEditorMode.mode !== GRAPH_EDITOR_MODE.GRAMMAR_TEXT) ||
        editorStore.graphState.isUpdatingGraph) &&
        !editorStore.graphManagerState.graphBuildState.hasFailed;
    const showExplorerTrees = editorStore.graphManagerState.graphBuildState.hasSucceeded &&
        editorStore.explorerTreeState.buildState.hasCompleted &&
        // NOTE: if not in viewer mode, we would only show the explorer tree
        // when graph is properly observed to make sure edit after that can trigger
        // change detection. Realistically, this doesn't not affect user as they
        // don't edit elements that fast in form mode, but this could throw off
        // test runner
        (editorStore.isInViewerMode ||
            editorStore.graphEditorMode.mode === GRAPH_EDITOR_MODE.GRAMMAR_TEXT ||
            editorStore.changeDetectionState.graphObserveState.hasSucceeded);
    // conflict resolution
    const showConflictResolutionContent = editorStore.isInConflictResolutionMode &&
        !editorStore.conflictResolutionState.hasResolvedAllConflicts;
    const goToConflictResolutionTab = () => editorStore.setActiveActivity(ACTIVITY_MODE.CONFLICT_RESOLUTION);
    const buildGrapnInConflictResolutionMode = () => {
        editorStore.conflictResolutionState.confirmHasResolvedAllConflicts();
        flowResult(editorStore.conflictResolutionState.buildGraphInConflictResolutionMode()).catch(applicationStore.alertUnhandledError);
    };
    return (_jsxs("div", { className: "panel explorer", children: [_jsxs("div", { className: "panel__header side-bar__header", children: [_jsx("div", { className: "panel__header__title", children: _jsx("div", { className: "panel__header__title__content side-bar__header__title__content", children: "EXPLORER" }) }), editorStore.editorMode.disableEditing &&
                        !editorStore.editorMode.label && (_jsxs("div", { className: "panel__header__title side-bar__header__title__viewer-mode-badge", children: [_jsx(LockIcon, {}), "READ-ONLY"] })), editorStore.editorMode.label && (_jsx("div", { className: "panel__header__title side-bar__header__title__viewer-mode-badge", children: editorStore.editorMode.label }))] }), _jsx("div", { className: "panel__content side-bar__content", children: _jsxs("div", { className: "panel explorer", children: [_jsxs("div", { className: "panel__header explorer__header", children: [sdlcState.currentProject && (_jsxs(_Fragment, { children: [_jsx("div", { className: "panel__header__title__label", children: sdlcState.currentWorkspace && !editorStore.isInViewerMode
                                                ? 'workspace'
                                                : 'project' }), _jsxs("div", { className: "panel__header__title__content", children: [editorStore.isInViewerMode && sdlcState.currentProject.name, !editorStore.isInViewerMode &&
                                                    (sdlcState.currentWorkspace?.workspaceId ?? '(unknown) ')] })] })), _jsx(ProjectExplorerActionPanel, { disabled: !editorStore.explorerTreeState.buildState.hasCompleted })] }), editorStore.explorerTreeState.buildState.hasCompleted && (_jsx(CreateNewElementModal, {})), _jsxs("div", { className: "panel__content explorer__content__container", children: [showConflictResolutionContent && (_jsxs(_Fragment, { children: [!editorStore.conflictResolutionState.conflicts.length && (_jsxs("div", { className: "explorer__content--empty", children: [_jsx("div", { className: "explorer__content--empty__text", children: "All conflicts have been resolved, you can build the graph now to start testing your changes" }), _jsx("button", { className: "btn--dark btn--conflict btn--important explorer__content--empty__btn", onClick: buildGrapnInConflictResolutionMode, children: "Build Graph" })] })), Boolean(editorStore.conflictResolutionState.conflicts.length) && (_jsxs("div", { className: "explorer__content--empty", children: [_jsx("div", { className: "explorer__content--empty__text", children: `Can't build graph as workspace contains merge conflicts, please resolve them before trying to build the graph again` }), _jsx("button", { className: "btn--dark btn--conflict btn--important explorer__content--empty__btn", onClick: goToConflictResolutionTab, children: "Resolve Merge Conflicts" })] }))] })), !showConflictResolutionContent && (_jsxs(_Fragment, { children: [_jsx(PanelLoadingIndicator, { isLoading: isLoading }), showExplorerTrees && _jsx(ExplorerTrees, {}), !showExplorerTrees &&
                                            !editorStore.graphManagerState.graphBuildState.hasFailed && (_jsx("div", { className: "explorer__content__progress-msg", children: editorStore.initState.message ??
                                                editorStore.graphManagerState.systemBuildState
                                                    .message ??
                                                editorStore.graphManagerState.dependenciesBuildState
                                                    .message ??
                                                editorStore.graphManagerState.generationsBuildState
                                                    .message ??
                                                editorStore.graphManagerState.graphBuildState.message ??
                                                editorStore.changeDetectionState.graphObserveState
                                                    .message })), !showExplorerTrees &&
                                            editorStore.graphManagerState.graphBuildState.hasFailed && (_jsx(BlankPanelContent, { children: _jsxs("div", { className: "explorer__content__failure-notice", children: [_jsx("div", { className: "explorer__content__failure-notice__icon", children: _jsx(ExclamationTriangleIcon, {}) }), _jsx("div", { className: "explorer__content__failure-notice__text", children: "Failed to build graph" })] }) }))] }))] })] }) }), editorStore.legendSQLStudioPlaygroundState.isOpen && (_jsx(LegendSQLPlaygroundModal, { playgroundState: editorStore.legendSQLStudioPlaygroundState }))] }));
});
//# sourceMappingURL=Explorer.js.map