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 { useState, useCallback, useRef } from 'react';
import { observer } from 'mobx-react-lite';
import { UMLEditorState, UML_EDITOR_TAB, } from '../../../../stores/editor/editor-state/element-editor-state/UMLEditorState.js';
import { useDrag, useDrop } from 'react-dnd';
import { CORE_DND_TYPE, } from '../../../../stores/editor/utils/DnDUtils.js';
import { prettyCONSTName } from '@finos/legend-shared';
import { BlankPanelContent, clsx, getCollapsiblePanelGroupProps, InputWithInlineValidation, ResizablePanel, ResizablePanelGroup, ResizablePanelSplitter, ResizablePanelSplitterLine, PlusIcon, TimesIcon, LongArrowRightIcon, LockIcon, FireIcon, StickArrowCircleRightIcon, PanelEntryDragHandle, DragPreviewLayer, useDragPreviewLayer, PanelDropZone, Panel, PanelContent, PanelDnDEntry, PanelHeader, PanelHeaderActionItem, PanelHeaderActions, PanelContentLists, } from '@finos/legend-art';
import { LEGEND_STUDIO_TEST_ID } from '../../../../__lib__/LegendStudioTesting.js';
import { StereotypeDragPreviewLayer, StereotypeSelector, } from './StereotypeSelector.js';
import { TaggedValueDragPreviewLayer, TaggedValueEditor, } from './TaggedValueEditor.js';
import { useEditorStore } from '../../EditorStoreProvider.js';
import { Profile, StereotypeExplicitReference, stub_TaggedValue, stub_Tag, stub_Profile, stub_Stereotype, stub_Enum, } from '@finos/legend-graph';
import { enum_setName, annotatedElement_deleteStereotype, annotatedElement_addStereotype, annotatedElement_addTaggedValue, annotatedElement_deleteTaggedValue, enum_deleteValue, enum_addValue, enum_swapValues, } from '../../../../stores/graph-modifier/DomainGraphModifierHelper.js';
import { useApplicationNavigationContext } from '@finos/legend-application';
import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../../../__lib__/LegendStudioApplicationNavigationContext.js';
const ENUM_VALUE_DND_TYPE = 'ENUMERATION';
const EnumBasicEditor = observer((props) => {
    const ref = useRef(null);
    const handleRef = useRef(null);
    const { enumValue, selectValue, deleteValue, isReadOnly } = props;
    const changeValue = (event) => {
        enum_setName(enumValue, event.target.value);
    };
    const isEnumValueDuplicated = (val) => enumValue._OWNER.values.filter((value) => value.name === val.name)
        .length >= 2;
    // Drag and Drop
    const handleHover = useCallback((item) => {
        const draggingEnumeration = item.enumValue;
        const hoveredEnumeration = enumValue;
        enum_swapValues(enumValue._OWNER, draggingEnumeration, hoveredEnumeration);
    }, [enumValue]);
    const [{ isBeingDraggedEnumeration }, dropConnector] = useDrop(() => ({
        accept: [ENUM_VALUE_DND_TYPE],
        hover: (item) => handleHover(item),
        collect: (monitor) => ({
            isBeingDraggedEnumeration: monitor.getItem()?.enumValue,
        }),
    }), [handleHover]);
    const isBeingDragged = enumValue === isBeingDraggedEnumeration;
    const [, dragConnector, dragPreviewConnector] = useDrag(() => ({
        type: ENUM_VALUE_DND_TYPE,
        item: () => ({
            enumValue: enumValue,
        }),
    }), [enumValue]);
    dragConnector(handleRef);
    dropConnector(ref);
    useDragPreviewLayer(dragPreviewConnector);
    return (_jsxs(PanelDnDEntry, { ref: ref, showPlaceholder: isBeingDragged, placeholder: _jsx("div", { className: "dnd__placeholder--light" }), className: "enum-basic-editor__container", children: [_jsx(PanelEntryDragHandle, { dragSourceConnector: handleRef, isDragging: isBeingDragged }), _jsxs("div", { className: "enum-basic-editor", children: [_jsx(InputWithInlineValidation, { className: "enum-basic-editor__name input-group__input", spellCheck: false, disabled: isReadOnly, value: enumValue.name, onChange: changeValue, placeholder: "Enum name", error: isEnumValueDuplicated(enumValue) ? 'Duplicated enum' : undefined }), _jsx("button", { className: "uml-element-editor__basic__detail-btn", onClick: selectValue, tabIndex: -1, title: "See detail", children: _jsx(LongArrowRightIcon, {}) }), !isReadOnly && (_jsx("button", { className: "uml-element-editor__remove-btn", disabled: isReadOnly, onClick: deleteValue, tabIndex: -1, title: "Remove", children: _jsx(TimesIcon, {}) }))] })] }));
});
const EnumEditor = observer((props) => {
    const { _enum, deselectValue, isReadOnly } = props;
    // Tab
    const [selectedTab, setSelectedTab] = useState(UML_EDITOR_TAB.TAGGED_VALUES);
    const tabs = [UML_EDITOR_TAB.TAGGED_VALUES, UML_EDITOR_TAB.STEREOTYPES];
    const changeTab = (tab) => () => setSelectedTab(tab);
    // Tagged value and Stereotype
    let addButtonTitle = '';
    switch (selectedTab) {
        case UML_EDITOR_TAB.TAGGED_VALUES:
            addButtonTitle = 'Add tagged value';
            break;
        case UML_EDITOR_TAB.STEREOTYPES:
            addButtonTitle = 'Add stereotype';
            break;
        default:
            break;
    }
    const addValue = () => {
        if (!isReadOnly) {
            if (selectedTab === UML_EDITOR_TAB.TAGGED_VALUES) {
                annotatedElement_addTaggedValue(_enum, stub_TaggedValue(stub_Tag(stub_Profile())));
            }
            else if (selectedTab === UML_EDITOR_TAB.STEREOTYPES) {
                annotatedElement_addStereotype(_enum, StereotypeExplicitReference.create(stub_Stereotype(stub_Profile())));
            }
        }
    };
    const _deleteStereotype = (val) => () => annotatedElement_deleteStereotype(_enum, val);
    const _deleteTaggedValue = (val) => () => annotatedElement_deleteTaggedValue(_enum, val);
    // Drag and Drop
    const handleDropTaggedValue = useCallback((item) => {
        if (!isReadOnly && item.data.packageableElement instanceof Profile) {
            annotatedElement_addTaggedValue(_enum, stub_TaggedValue(stub_Tag(item.data.packageableElement)));
        }
    }, [_enum, isReadOnly]);
    const [{ isTaggedValueDragOver }, taggedValueDropConnector] = useDrop(() => ({
        accept: [CORE_DND_TYPE.PROJECT_EXPLORER_PROFILE],
        drop: (item) => handleDropTaggedValue(item),
        collect: (monitor) => ({
            isTaggedValueDragOver: monitor.isOver({ shallow: true }),
        }),
    }), [handleDropTaggedValue]);
    const handleDropStereotype = useCallback((item) => {
        if (!isReadOnly && item.data.packageableElement instanceof Profile) {
            annotatedElement_addStereotype(_enum, StereotypeExplicitReference.create(stub_Stereotype(item.data.packageableElement)));
        }
    }, [_enum, isReadOnly]);
    const [{ isStereotypeDragOver }, stereotypeDropConnector] = useDrop(() => ({
        accept: [CORE_DND_TYPE.PROJECT_EXPLORER_PROFILE],
        drop: (item) => handleDropStereotype(item),
        collect: (monitor) => ({
            isStereotypeDragOver: monitor.isOver({ shallow: true }),
        }),
    }), [handleDropStereotype]);
    return (_jsx("div", { className: "uml-element-editor enum-editor", children: _jsxs("div", { "data-testid": LEGEND_STUDIO_TEST_ID.PANEL, className: "panel", children: [_jsxs(PanelHeader, { children: [_jsxs("div", { className: "panel__header__title", children: [isReadOnly && (_jsx("div", { className: "uml-element-editor__header__lock", children: _jsx(LockIcon, {}) })), _jsx("div", { className: "panel__header__title__label", children: "enum" }), _jsx("div", { className: "panel__header__title__content", children: _enum.name })] }), _jsx(PanelHeaderActions, { children: _jsx(PanelHeaderActionItem, { onClick: deselectValue, title: "Close", children: _jsx(TimesIcon, {}) }) })] }), _jsxs("div", { "data-testid": LEGEND_STUDIO_TEST_ID.UML_ELEMENT_EDITOR__TABS_HEADER, className: "panel__header uml-element-editor__tabs__header", children: [_jsx("div", { className: "uml-element-editor__tabs", children: tabs.map((tab) => (_jsx("div", { onClick: changeTab(tab), className: clsx('uml-element-editor__tab', {
                                    'uml-element-editor__tab--active': tab === selectedTab,
                                }), children: prettyCONSTName(tab) }, tab))) }), _jsx(PanelHeaderActions, { children: _jsx(PanelHeaderActionItem, { disabled: isReadOnly, onClick: addValue, title: addButtonTitle, children: _jsx(PlusIcon, {}) }) })] }), _jsxs(PanelContent, { children: [selectedTab === UML_EDITOR_TAB.TAGGED_VALUES && (_jsx(PanelDropZone, { isDragOver: isTaggedValueDragOver && !isReadOnly, dropTargetConnector: taggedValueDropConnector, children: _jsxs(PanelContentLists, { children: [_jsx(TaggedValueDragPreviewLayer, {}), _enum.taggedValues.map((taggedValue) => (_jsx(TaggedValueEditor, { annotatedElement: _enum, taggedValue: taggedValue, deleteValue: _deleteTaggedValue(taggedValue), isReadOnly: isReadOnly }, taggedValue._UUID)))] }) })), selectedTab === UML_EDITOR_TAB.STEREOTYPES && (_jsx(PanelDropZone, { isDragOver: isStereotypeDragOver && !isReadOnly, dropTargetConnector: stereotypeDropConnector, children: _jsxs(PanelContentLists, { children: [_jsx(StereotypeDragPreviewLayer, {}), _enum.stereotypes.map((stereotype) => (_jsx(StereotypeSelector, { annotatedElement: _enum, stereotype: stereotype, deleteStereotype: _deleteStereotype(stereotype), isReadOnly: isReadOnly }, stereotype.value._UUID)))] }) }))] })] }) }));
});
export const EnumerationEditor = observer((props) => {
    const { enumeration } = props;
    const editorStore = useEditorStore();
    const editorState = editorStore.tabManagerState.getCurrentEditorState(UMLEditorState);
    const isReadOnly = editorState.isReadOnly;
    // Selected enum value
    const [selectedEnum, setSelectedEnum] = useState();
    const deselectValue = () => setSelectedEnum(undefined);
    const selectValue = (val) => () => setSelectedEnum(val);
    // Tab
    const selectedTab = editorState.selectedTab;
    const tabs = [
        UML_EDITOR_TAB.ENUM_VALUES,
        UML_EDITOR_TAB.TAGGED_VALUES,
        UML_EDITOR_TAB.STEREOTYPES,
    ];
    const changeTab = (tab) => () => {
        editorState.setSelectedTab(tab);
        setSelectedEnum(undefined);
    };
    // Tagged value and Stereotype
    let addButtonTitle = '';
    switch (selectedTab) {
        case UML_EDITOR_TAB.ENUM_VALUES:
            addButtonTitle = 'Add enum value';
            break;
        case UML_EDITOR_TAB.TAGGED_VALUES:
            addButtonTitle = 'Add tagged value';
            break;
        case UML_EDITOR_TAB.STEREOTYPES:
            addButtonTitle = 'Add stereotype';
            break;
        default:
            break;
    }
    const add = () => {
        if (!isReadOnly) {
            if (selectedTab === UML_EDITOR_TAB.ENUM_VALUES) {
                enum_addValue(enumeration, stub_Enum(enumeration));
            }
            else if (selectedTab === UML_EDITOR_TAB.TAGGED_VALUES) {
                annotatedElement_addTaggedValue(enumeration, stub_TaggedValue(stub_Tag(stub_Profile())));
            }
            else if (selectedTab === UML_EDITOR_TAB.STEREOTYPES) {
                annotatedElement_addStereotype(enumeration, StereotypeExplicitReference.create(stub_Stereotype(stub_Profile())));
            }
        }
    };
    const deleteValue = (val) => () => {
        enum_deleteValue(enumeration, val);
        if (val === selectedEnum) {
            setSelectedEnum(undefined);
        }
    };
    const _deleteStereotype = (val) => () => annotatedElement_deleteStereotype(enumeration, val);
    const _deleteTaggedValue = (val) => () => annotatedElement_deleteTaggedValue(enumeration, val);
    // Drag and Drop
    const handleDropTaggedValue = useCallback((item) => {
        if (!isReadOnly && item.data.packageableElement instanceof Profile) {
            annotatedElement_addTaggedValue(enumeration, stub_TaggedValue(stub_Tag(item.data.packageableElement)));
        }
    }, [enumeration, isReadOnly]);
    const [{ isTaggedValueDragOver }, taggedValueDropConnector] = useDrop(() => ({
        accept: [CORE_DND_TYPE.PROJECT_EXPLORER_PROFILE],
        drop: (item) => handleDropTaggedValue(item),
        collect: (monitor) => ({
            isTaggedValueDragOver: monitor.isOver({ shallow: true }),
        }),
    }), [handleDropTaggedValue]);
    const handleDropStereotype = useCallback((item) => {
        if (!isReadOnly && item.data.packageableElement instanceof Profile) {
            annotatedElement_addStereotype(enumeration, StereotypeExplicitReference.create(stub_Stereotype(item.data.packageableElement)));
        }
    }, [enumeration, isReadOnly]);
    const [{ isStereotypeDragOver }, stereotypeDropConnector] = useDrop(() => ({
        accept: [CORE_DND_TYPE.PROJECT_EXPLORER_PROFILE],
        drop: (item) => handleDropStereotype(item),
        collect: (monitor) => ({
            isStereotypeDragOver: monitor.isOver({ shallow: true }),
        }),
    }), [handleDropStereotype]);
    // Generation
    const generationParentElementPath = editorStore.graphState.graphGenerationState.findGenerationParentPath(enumeration.path);
    const generationParentElement = generationParentElementPath
        ? editorStore.graphManagerState.graph.getNullableElement(generationParentElementPath)
        : undefined;
    const visitGenerationParentElement = () => {
        if (generationParentElement) {
            editorStore.graphEditorMode.openElement(generationParentElement);
        }
    };
    useApplicationNavigationContext(LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.ENUMERATION_EDITOR);
    // layout
    const enumEditorCollapsiblePanelGroupProps = getCollapsiblePanelGroupProps(!selectedEnum, {
        size: 250,
    });
    return (_jsx("div", { "data-testid": LEGEND_STUDIO_TEST_ID.ENUMERATION_EDITOR, className: "uml-element-editor enumeration-editor", children: _jsxs(ResizablePanelGroup, { orientation: "horizontal", children: [_jsx(ResizablePanel, { ...enumEditorCollapsiblePanelGroupProps.remainingPanel, minSize: 56, children: _jsxs(Panel, { children: [_jsxs("div", { className: "panel__header", children: [_jsxs("div", { className: "panel__header__title", children: [_jsx("div", { className: "panel__header__title__label", children: "enumeration" }), _jsx("div", { className: "panel__header__title__content", children: enumeration.name })] }), _jsx("div", { className: "panel__header__actions", children: generationParentElement && (_jsxs("button", { className: "uml-element-editor__header__generation-origin", onClick: visitGenerationParentElement, tabIndex: -1, title: `Visit generation parent '${generationParentElement.path}'`, children: [_jsx("div", { className: "uml-element-editor__header__generation-origin__label", children: _jsx(FireIcon, {}) }), _jsx("div", { className: "uml-element-editor__header__generation-origin__parent-name", children: generationParentElement.name }), _jsx("div", { className: "uml-element-editor__header__generation-origin__visit-btn", children: _jsx(StickArrowCircleRightIcon, {}) })] })) })] }), _jsxs("div", { "data-testid": LEGEND_STUDIO_TEST_ID.UML_ELEMENT_EDITOR__TABS_HEADER, className: "panel__header uml-element-editor__tabs__header", children: [_jsx("div", { className: "uml-element-editor__tabs", children: tabs.map((tab) => (_jsx("div", { onClick: changeTab(tab), className: clsx('uml-element-editor__tab', {
                                                'uml-element-editor__tab--active': tab === selectedTab,
                                            }), children: prettyCONSTName(tab) }, tab))) }), _jsx("div", { className: "panel__header__actions", children: _jsx("button", { className: "panel__header__action", onClick: add, tabIndex: -1, title: addButtonTitle, children: _jsx(PlusIcon, {}) }) })] }), _jsxs(PanelContent, { children: [selectedTab === UML_EDITOR_TAB.ENUM_VALUES && (_jsxs(PanelContentLists, { children: [_jsx(DragPreviewLayer, { labelGetter: (item) => item.enumValue.name === ''
                                                    ? '(unknown)'
                                                    : item.enumValue.name, types: [ENUM_VALUE_DND_TYPE] }), enumeration.values.map((enumValue) => (_jsx(EnumBasicEditor, { enumValue: enumValue, deleteValue: deleteValue(enumValue), selectValue: selectValue(enumValue), isReadOnly: isReadOnly }, enumValue._UUID)))] })), selectedTab === UML_EDITOR_TAB.TAGGED_VALUES && (_jsx(PanelDropZone, { isDragOver: isTaggedValueDragOver && !isReadOnly, dropTargetConnector: taggedValueDropConnector, children: _jsxs(PanelContentLists, { children: [_jsx(TaggedValueDragPreviewLayer, {}), enumeration.taggedValues.map((taggedValue) => (_jsx(TaggedValueEditor, { annotatedElement: enumeration, taggedValue: taggedValue, deleteValue: _deleteTaggedValue(taggedValue), isReadOnly: isReadOnly }, taggedValue._UUID)))] }) })), selectedTab === UML_EDITOR_TAB.STEREOTYPES && (_jsx(PanelDropZone, { isDragOver: isStereotypeDragOver && !isReadOnly, dropTargetConnector: stereotypeDropConnector, children: _jsxs(PanelContentLists, { children: [_jsx(StereotypeDragPreviewLayer, {}), enumeration.stereotypes.map((stereotype) => (_jsx(StereotypeSelector, { annotatedElement: enumeration, stereotype: stereotype, deleteStereotype: _deleteStereotype(stereotype), isReadOnly: isReadOnly }, stereotype.value._UUID)))] }) }))] })] }) }), _jsx(ResizablePanelSplitter, { children: _jsx(ResizablePanelSplitterLine, { color: "var(--color-light-grey-200)" }) }), _jsx(ResizablePanel, { ...enumEditorCollapsiblePanelGroupProps.collapsiblePanel, direction: -1, children: selectedEnum ? (_jsx(EnumEditor, { _enum: selectedEnum, deselectValue: deselectValue, isReadOnly: isReadOnly })) : (_jsx("div", { className: "uml-element-editor__sub-editor", children: _jsx(BlankPanelContent, { children: "No enum selected" }) })) })] }) }));
});
//# sourceMappingURL=EnumerationEditor.js.map