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 { useEffect, useCallback } from 'react';
import { observer } from 'mobx-react-lite';
import { MappingEditorState } from '../../../../stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.js';
import { CustomSelectorInput, createFilter, TimesIcon, ArrowCircleRightIcon, PlusIcon, PanelDropZone, Panel, PanelContent, PanelHeaderActions, PanelHeader, PanelHeaderActionItem, } from '@finos/legend-art';
import { CORE_DND_TYPE, } from '../../../../stores/editor/utils/DnDUtils.js';
import { useDrop } from 'react-dnd';
import { noop } from '@finos/legend-shared';
import { MappingElementDecorator, MappingElementDecorationCleaner, } from '../../../../stores/editor/editor-state/element-editor-state/mapping/MappingElementDecorator.js';
import { OperationSetImplementation, OperationType, SetImplementation, SetImplementationContainer, InferableMappingElementIdExplicitValue, PackageableElementExplicitReference, SetImplementationExplicitReference, InferableMappingElementRootExplicitValue, getClassMappingsByClass, getAllChildSetImplementations, stub_Mapping, stub_Class, } from '@finos/legend-graph';
import { useEditorStore } from '../../EditorStoreProvider.js';
import { operationMapping_addParameter, operationMapping_changeParameter, operationMapping_deleteParameter, } from '../../../../stores/graph-modifier/DSL_Mapping_GraphModifierHelper.js';
export const OperationSetImplementationEditor = observer((props) => {
    const { setImplementation, isReadOnly } = props;
    const editorStore = useEditorStore();
    const mappingEditorState = editorStore.tabManagerState.getCurrentEditorState(MappingEditorState);
    const mapping = mappingEditorState.mapping;
    // Parameters
    const setImplementationOptions = getClassMappingsByClass(mapping, setImplementation.class.value)
        .filter((si) => 
    // filter out the current set impl
    si.id.value !== setImplementation.id.value &&
        // filter out set impls already included through a container or the actual container itself
        !getAllChildSetImplementations(setImplementation).includes(si))
        .map((si) => ({ value: si, label: si.id.value }));
    const filterOption = createFilter({
        stringify: (option) => option.data.label,
    });
    const addParameter = () => operationMapping_addParameter(setImplementation, new SetImplementationContainer(SetImplementationExplicitReference.create(new OperationSetImplementation(InferableMappingElementIdExplicitValue.create('', ''), stub_Mapping(), PackageableElementExplicitReference.create(stub_Class()), InferableMappingElementRootExplicitValue.create(false), OperationType.STORE_UNION))));
    const deleteParameter = (val) => () => operationMapping_deleteParameter(setImplementation, val);
    const changeParamater = (val) => (option) => {
        const setImpl = option?.value;
        if (setImpl) {
            operationMapping_changeParameter(setImplementation, val, new SetImplementationContainer(SetImplementationExplicitReference.create(setImpl)));
        }
    };
    // Drag and Drop
    const handleDrop = useCallback((item) => {
        const mappingElement = item.data;
        if (mappingElement instanceof SetImplementation &&
            setImplementation.operation !== OperationType.INHERITANCE &&
            mappingElement.class.value === setImplementation.class.value &&
            !setImplementation.parameters.find((param) => param.setImplementation.value === mappingElement) &&
            mappingElement !== setImplementation) {
            operationMapping_addParameter(setImplementation, new SetImplementationContainer(SetImplementationExplicitReference.create(mappingElement)));
        }
    }, [setImplementation]);
    const [{ isDragOver }, dropConnector] = useDrop(() => ({
        accept: CORE_DND_TYPE.MAPPING_EXPLORER_CLASS_MAPPING,
        drop: (item) => handleDrop(item),
        collect: (monitor) => ({
            isDragOver: monitor.isOver({ shallow: true }),
        }),
    }), [handleDrop]);
    // actions
    const visit = (param) => () => {
        const parent = param.setImplementation.value._PARENT;
        // TODO: think more about this flow. Right now we open the mapping element in the parent mapping
        if (parent !== mappingEditorState.element) {
            editorStore.graphEditorMode.openElement(parent);
            editorStore.tabManagerState
                .getCurrentEditorState(MappingEditorState)
                .openMappingElement(param.setImplementation.value, false);
        }
        else {
            mappingEditorState.openMappingElement(param.setImplementation.value, true);
        }
    };
    useEffect(() => {
        if (!isReadOnly) {
            setImplementation.accept_SetImplementationVisitor(new MappingElementDecorator(editorStore));
        }
        return isReadOnly
            ? noop()
            : () => setImplementation.accept_SetImplementationVisitor(new MappingElementDecorationCleaner(editorStore));
    }, [setImplementation, isReadOnly, editorStore]);
    return (_jsx("div", { className: "mapping-element-editor__content", children: _jsxs(Panel, { children: [_jsxs(PanelHeader, { children: [_jsx("div", { className: "panel__header__title", children: _jsx("div", { className: "panel__header__title__content", children: "PARAMETERS" }) }), _jsx(PanelHeaderActions, { children: _jsx(PanelHeaderActionItem, { disabled: isReadOnly ||
                                    setImplementation.operation === OperationType.INHERITANCE, onClick: addParameter, title: "Add parameter", children: _jsx(PlusIcon, {}) }) })] }), _jsx(PanelDropZone, { isDragOver: isDragOver && !isReadOnly, dropTargetConnector: dropConnector, children: _jsx(PanelContent, { children: setImplementation.parameters.map((param) => (_jsxs("div", { className: "operation-mapping-editor__parameter", children: [_jsx("div", { className: "operation-mapping-editor__parameter__selector", children: _jsx(CustomSelectorInput, { options: setImplementationOptions, disabled: isReadOnly, onChange: changeParamater(param), filterOption: filterOption, value: {
                                            value: param.setImplementation.value,
                                            label: param.setImplementation.value.id.value,
                                        }, placeholder: "Select parameter ID" }) }), _jsx("button", { className: "operation-mapping-editor__parameter__visit-btn", onClick: visit(param), tabIndex: -1, title: "Visit mapping element", children: _jsx(ArrowCircleRightIcon, {}) }), !isReadOnly && (_jsx("button", { className: "operation-mapping-editor__parameter__remove-btn", disabled: isReadOnly, onClick: deleteParameter(param), tabIndex: -1, title: "Remove", children: _jsx(TimesIcon, {}) }))] }, param._UUID))) }) })] }) }));
});
//# sourceMappingURL=OperationSetImplementationEditor.js.map