import { jsx as _jsx, Fragment as _Fragment, 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, useRef, useEffect, useMemo } from 'react';
import { observer } from 'mobx-react-lite';
import { MINIMUM_SERVICE_OWNERS, ServiceEditorState, SERVICE_TAB, OWNERSHIP_OPTIONS, } from '../../../../stores/editor/editor-state/element-editor-state/service/ServiceEditorState.js';
import { clsx, PencilIcon, LockIcon, TimesIcon, ErrorIcon, PanelFormBooleanField, PanelForm, CustomSelectorInput, PanelFormValidatedTextField, PanelContentLists, } from '@finos/legend-art';
import { debounce, prettyCONSTName } from '@finos/legend-shared';
import { ServiceExecutionEditor } from './ServiceExecutionEditor.js';
import { LEGEND_STUDIO_TEST_ID } from '../../../../__lib__/LegendStudioTesting.js';
import { ServiceRegistrationEditor } from './ServiceRegistrationEditor.js';
import { useEditorStore } from '../../EditorStoreProvider.js';
import { service_addOwner, service_deleteOwner, service_removePatternParameter, service_setAutoActivateUpdates, service_setDocumentation, service_setPattern, service_setMcpServer, service_updateOwner, service_deploymentOwnership, service_addUserOwnership, service_updateUserOwnership, service_deleteValueFromUserOwnership, } from '../../../../stores/graph-modifier/DSL_Service_GraphModifierHelper.js';
import { useApplicationNavigationContext, useApplicationStore, } from '@finos/legend-application';
import { validate_ServicePattern, validate_ServiceMcpServer, DeploymentOwnership, UserListOwnership, } from '@finos/legend-graph';
import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../../../__lib__/LegendStudioApplicationNavigationContext.js';
import { ServiceTestableEditor } from './testable/ServiceTestableEditor.js';
import { flowResult } from 'mobx';
import { LEGEND_STUDIO_DOCUMENTATION_KEY } from '../../../../__lib__/LegendStudioDocumentation.js';
import { DocumentationLink } from '@finos/legend-lego/application';
import { ServicePostValidationsEditor } from './ServicePostValidationEditor.js';
const ServiceGeneralEditor = observer(() => {
    const editorStore = useEditorStore();
    const serviceState = editorStore.tabManagerState.getCurrentEditorState(ServiceEditorState);
    const service = serviceState.service;
    const ownership = service.ownership;
    const isReadOnly = serviceState.isReadOnly;
    // Pattern
    const patternRef = useRef(null);
    const [pattern, setPattern] = useState(service.pattern);
    const updatePattern = (newPattern) => {
        if (!isReadOnly) {
            service_setPattern(service, newPattern);
        }
    };
    const getPatternValidationMessage = (inputPattern) => {
        const patternValidationResult = validate_ServicePattern(inputPattern);
        return patternValidationResult
            ? patternValidationResult.messages[0]
            : undefined;
    };
    const removePatternParameter = (val) => () => {
        service_removePatternParameter(service, val);
        setPattern(service.pattern);
    };
    //McpServer
    const [mcpServer, setMcpServer] = useState(service.mcpServer);
    const updateMcpServer = (newMcpServer) => {
        if (!isReadOnly) {
            service_setMcpServer(service, newMcpServer);
            setMcpServer(service.mcpServer);
        }
    };
    const getMcpServerValidationMessage = (inputMcpServer) => {
        const mcpServerValidationResult = validate_ServiceMcpServer(inputMcpServer);
        return mcpServerValidationResult
            ? mcpServerValidationResult.messages[0]
            : undefined;
    };
    // Owners
    const owners = service.owners;
    const [showOwnerEditInput, setShowOwnerEditInput] = useState(false);
    const applicationStore = useApplicationStore();
    const [ownerInputValue, setOwnerInputValue] = useState('');
    const [ownerInputs, setOwnerInputs] = useState([]);
    const [searchText, setSearchText] = useState('');
    const [userOptions, setUserOptions] = useState([]);
    const [isLoadingUsers, setIsLoadingUsers] = useState(false);
    const showAddOwnerInput = () => setShowOwnerEditInput(true);
    const showEditOwnerInput = (value, idx) => () => {
        setOwnerInputValue(value);
        setShowOwnerEditInput(idx);
    };
    const hideAddOrEditOwnerInput = () => {
        setShowOwnerEditInput(false);
        setOwnerInputValue('');
    };
    const changeOwnerInputValue = (event) => setOwnerInputValue(event.target.value);
    const addOwner = () => {
        ownerInputs.forEach((value) => {
            if (value && !isReadOnly && !owners.includes(value)) {
                service_addOwner(service, value);
            }
        });
        hideAddOrEditOwnerInput();
    };
    const updateOwner = (idx) => () => {
        if (ownerInputValue && !isReadOnly && !owners.includes(ownerInputValue)) {
            service_updateOwner(service, ownerInputValue, idx);
        }
    };
    const deleteOwner = (idx) => () => {
        if (!isReadOnly) {
            service_deleteOwner(service, idx);
            // Since we keep track of the value currently being edited using the index, we have to account for it as we delete entry
            if (typeof showOwnerEditInput === 'number' &&
                showOwnerEditInput > idx) {
                setShowOwnerEditInput(showOwnerEditInput - 1);
            }
        }
    };
    const changeUserOwnerInputValue = (event) => setOwnerInputValue(event.target.value);
    const updateDeploymentIdentifier = (event) => {
        if (!isReadOnly && ownership instanceof DeploymentOwnership) {
            service_deploymentOwnership(ownership, event.target.value);
        }
    };
    const addUser = () => {
        ownerInputs.forEach((value) => {
            if (value &&
                !isReadOnly &&
                ownership instanceof UserListOwnership &&
                !ownership.users.includes(value)) {
                service_addUserOwnership(ownership, value);
            }
        });
        hideAddOrEditOwnerInput();
    };
    const updateUser = (idx) => () => {
        if (ownerInputValue &&
            !isReadOnly &&
            ownership instanceof UserListOwnership &&
            !ownership.users.includes(ownerInputValue)) {
            service_updateUserOwnership(ownership, ownerInputValue, idx);
        }
    };
    const deleteUser = (idx) => () => {
        if (!isReadOnly && ownership instanceof UserListOwnership) {
            service_deleteValueFromUserOwnership(ownership, idx);
            // Since we keep track of the value currently being edited using the index, we have to account for it as we delete entry
            if (typeof showOwnerEditInput === 'number' &&
                showOwnerEditInput > idx) {
                setShowOwnerEditInput(showOwnerEditInput - 1);
            }
        }
    };
    // Other
    const changeDocumentation = (event) => {
        if (!isReadOnly) {
            service_setDocumentation(service, event.target.value);
        }
    };
    const toggleAutoActivateUpdates = () => {
        service_setAutoActivateUpdates(service, !service.autoActivateUpdates);
    };
    const debouncedSearchUsers = useMemo(() => debounce((input) => {
        setIsLoadingUsers(true);
        flowResult(serviceState.searchUsers(input))
            .then((users) => setUserOptions(users.map((u) => ({
            value: u.userId,
            label: u.userId,
        }))))
            .then(() => setIsLoadingUsers(false))
            .catch(serviceState.editorStore.applicationStore.alertUnhandledError);
    }, 500), [serviceState]);
    const onSearchTextChange = (value) => {
        if (value !== searchText) {
            setSearchText(value);
            debouncedSearchUsers.cancel();
            if (value.length >= 3) {
                debouncedSearchUsers(value);
            }
            else if (value.length === 0) {
                setUserOptions([]);
                setIsLoadingUsers(false);
            }
        }
    };
    const onUserOptionChange = (options) => {
        setOwnerInputs(options.map((op) => op.label));
        setUserOptions([]);
        debouncedSearchUsers.cancel();
        setIsLoadingUsers(false);
    };
    const onOwnershipChange = (val) => {
        if (val) {
            serviceState.setSelectedOwnership(val);
        }
    };
    useEffect(() => {
        patternRef.current?.focus();
    }, [serviceState]);
    return (_jsxs(PanelContentLists, { className: "service-editor__general", children: [_jsx(PanelForm, { children: _jsx(PanelFormValidatedTextField, { ref: patternRef, name: "URL Pattern", isReadOnly: isReadOnly, className: "service-editor__pattern__input", errorMessageClassName: "service-editor__pattern__input", prompt: _jsxs(_Fragment, { children: ["Specifies the URL pattern of the service (e.g. /myService/", _jsx("span", { className: "service-editor__pattern__example__param", children: `{param}` }), ")"] }), update: (value) => {
                        updatePattern(value ?? '');
                    }, validate: getPatternValidationMessage, value: pattern }) }), _jsx(PanelForm, { children: _jsxs("div", { className: "panel__content__form__section service-editor__parameters", children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Parameters" }), _jsx("div", { className: "panel__content__form__section__header__prompt", children: "URL parameters (each must be surrounded by curly braces) will be passed as arguments for the execution query. Note that if the service is configured to use multi-execution, one of the URL parameters must be chosen as the execution key." }), _jsxs("div", { className: "service-editor__parameters__list", children: [!service.patternParameters.length && (_jsx("div", { className: "service-editor__parameters__list__empty", children: "No parameter" })), Boolean(service.patternParameters.length) &&
                                    service.patternParameters.map((parameter) => (_jsxs("div", { className: "service-editor__parameter", children: [_jsx("div", { className: "service-editor__parameter__text", children: parameter }), _jsx("div", { className: "service-editor__parameter__actions", children: _jsx("button", { className: "service-editor__parameter__action", disabled: isReadOnly, onClick: removePatternParameter(parameter), title: "Remove parameter", tabIndex: -1, children: _jsx(TimesIcon, {}) }) })] }, parameter)))] })] }) }), _jsx(PanelForm, { children: _jsxs("div", { className: "panel__content__form__section", children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Documentation" }), _jsx("div", { className: "panel__content__form__section__header__prompt", children: `Provide a brief description of the service's functionalities and usage` }), _jsx("textarea", { className: "panel__content__form__section__textarea service-editor__documentation__input", spellCheck: false, disabled: isReadOnly, value: service.documentation, onChange: changeDocumentation })] }) }), _jsx(PanelForm, { children: _jsx(PanelFormBooleanField, { isReadOnly: isReadOnly, value: service.autoActivateUpdates, name: "Auto Activate Updates", prompt: "Specifies if the new generation should be automatically activated;\n        only valid when latest revision is selected upon service\n        registration", update: toggleAutoActivateUpdates }) }), _jsxs(PanelForm, { children: [owners.length === 0 && (_jsxs("div", { children: [_jsxs("div", { className: "panel__content__form__section", children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Ownership" }), _jsx("div", { className: "panel__content__form__section__header__prompt", children: "The ownership model you want to use to control your service." }), _jsx(CustomSelectorInput, { options: OWNERSHIP_OPTIONS, onChange: onOwnershipChange, value: serviceState.selectedOwnership, darkMode: !applicationStore.layoutService
                                            .TEMPORARY__isLightColorThemeEnabled })] }), ownership instanceof DeploymentOwnership && (_jsx("div", { className: "panel__content__form__section", children: _jsxs("div", { children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Deployment Identifier :" }), _jsx("input", { className: "panel__content__form__section__input", spellCheck: false, disabled: isReadOnly, value: ownership.identifier, onChange: updateDeploymentIdentifier })] }) })), ownership instanceof UserListOwnership && (_jsx("div", { className: "panel__content__form__section", children: _jsxs("div", { children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Users :" }), _jsxs("div", { className: "panel__content__form__section__list", children: [_jsxs("div", { className: "panel__content__form__section__list__items", "data-testid": LEGEND_STUDIO_TEST_ID.PANEL_CONTENT_FORM_SECTION_LIST_ITEMS, children: [ownership.users.map((value, idx) => (_jsx("div", { className: showOwnerEditInput === idx
                                                                ? 'panel__content__form__section__list__new-item'
                                                                : 'panel__content__form__section__list__item', children: showOwnerEditInput === idx ? (_jsxs(_Fragment, { children: [_jsx("input", { className: "panel__content__form__section__input panel__content__form__section__list__new-item__input", spellCheck: false, disabled: isReadOnly, value: ownerInputValue, onChange: changeUserOwnerInputValue }), _jsxs("div", { className: "panel__content__form__section__list__new-item__actions", children: [_jsx("button", { className: "panel__content__form__section__list__new-item__add-btn btn btn--dark", disabled: isReadOnly ||
                                                                                    ownership.users.includes(ownerInputValue), onClick: updateUser(idx), tabIndex: -1, children: "Save" }), _jsx("button", { className: "panel__content__form__section__list__new-item__cancel-btn btn btn--dark", disabled: isReadOnly, onClick: hideAddOrEditOwnerInput, tabIndex: -1, children: "Cancel" })] })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "panel__content__form__section__list__item__value", children: value }), _jsxs("div", { className: "panel__content__form__section__list__item__actions", children: [_jsx("button", { className: "panel__content__form__section__list__item__edit-btn", disabled: isReadOnly, onClick: showEditOwnerInput(value, idx), tabIndex: -1, children: _jsx(PencilIcon, {}) }), _jsx("button", { className: "panel__content__form__section__list__item__remove-btn", disabled: isReadOnly, onClick: deleteUser(idx), tabIndex: -1, children: _jsx(TimesIcon, {}) })] })] })) }, value))), showOwnerEditInput === true && (_jsxs("div", { className: "panel__content__form__section__list__new-item", children: [_jsx(CustomSelectorInput, { className: "service-editor__owner__selector", placeholder: "Enter an owner...", inputValue: searchText, options: userOptions, allowCreating: true, isLoading: isLoadingUsers, disabled: isReadOnly, darkMode: !applicationStore.layoutService
                                                                        .TEMPORARY__isLightColorThemeEnabled, onInputChange: onSearchTextChange, onChange: onUserOptionChange, isMulti: true }), _jsxs("div", { className: "panel__content__form__section__list__new-item__actions", children: [_jsx("button", { className: "panel__content__form__section__list__new-item__add-btn btn btn--dark service-editor__owner__action", disabled: isReadOnly ||
                                                                                ownerInputs.some((i) => ownership.users.includes(i)), onClick: addUser, tabIndex: -1, children: "Save" }), _jsx("button", { className: "panel__content__form__section__list__new-item__cancel-btn btn btn--dark service-editor__owner__action", disabled: isReadOnly, onClick: hideAddOrEditOwnerInput, tabIndex: -1, children: "Cancel" })] })] }))] }), ownership.users.length < MINIMUM_SERVICE_OWNERS &&
                                                    showOwnerEditInput !== true && (_jsxs("div", { className: "service-editor__owner__validation", title: `${MINIMUM_SERVICE_OWNERS} owners required`, children: [_jsx(ErrorIcon, {}), _jsx("div", { className: "service-editor__owner__validation-label", children: `Service requires at least ${MINIMUM_SERVICE_OWNERS} owners` })] })), showOwnerEditInput !== true && (_jsx("div", { className: "panel__content__form__section__list__new-item__add", children: _jsx("button", { className: "panel__content__form__section__list__new-item__add-btn btn btn--dark", disabled: isReadOnly, onClick: showAddOwnerInput, tabIndex: -1, title: "Add owner", children: "Add Value" }) }))] })] }) }))] })), owners.length > 0 && (_jsxs("div", { className: "panel__content__form__section", children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Owners (deprecated)" }), _jsx("div", { className: "panel__content__form__section__header__prompt", children: `Specifies who can manage and operate the service (requires minimum ${MINIMUM_SERVICE_OWNERS}
          owners).` }), _jsxs("div", { className: "panel__content__form__section__list", children: [_jsxs("div", { className: "panel__content__form__section__list__items", "data-testid": LEGEND_STUDIO_TEST_ID.PANEL_CONTENT_FORM_SECTION_LIST_ITEMS, children: [owners.map((value, idx) => (_jsx("div", { className: showOwnerEditInput === idx
                                                    ? 'panel__content__form__section__list__new-item'
                                                    : 'panel__content__form__section__list__item', children: showOwnerEditInput === idx ? (_jsxs(_Fragment, { children: [_jsx("input", { className: "panel__content__form__section__input panel__content__form__section__list__new-item__input", spellCheck: false, disabled: isReadOnly, value: ownerInputValue, onChange: changeOwnerInputValue }), _jsxs("div", { className: "panel__content__form__section__list__new-item__actions", children: [_jsx("button", { className: "panel__content__form__section__list__new-item__add-btn btn btn--dark", disabled: isReadOnly || owners.includes(ownerInputValue), onClick: updateOwner(idx), tabIndex: -1, children: "Save" }), _jsx("button", { className: "panel__content__form__section__list__new-item__cancel-btn btn btn--dark", disabled: isReadOnly, onClick: hideAddOrEditOwnerInput, tabIndex: -1, children: "Cancel" })] })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "panel__content__form__section__list__item__value", children: value }), _jsxs("div", { className: "panel__content__form__section__list__item__actions", children: [_jsx("button", { className: "panel__content__form__section__list__item__edit-btn", disabled: isReadOnly, onClick: showEditOwnerInput(value, idx), tabIndex: -1, children: _jsx(PencilIcon, {}) }), _jsx("button", { className: "panel__content__form__section__list__item__remove-btn", disabled: isReadOnly, onClick: deleteOwner(idx), tabIndex: -1, children: _jsx(TimesIcon, {}) })] })] })) }, value))), showOwnerEditInput === true && (_jsxs("div", { className: "panel__content__form__section__list__new-item", children: [_jsx(CustomSelectorInput, { className: "service-editor__owner__selector", placeholder: "Enter an owner...", inputValue: searchText, options: userOptions, allowCreating: true, isLoading: isLoadingUsers, disabled: isReadOnly, darkMode: !applicationStore.layoutService
                                                            .TEMPORARY__isLightColorThemeEnabled, onInputChange: onSearchTextChange, onChange: onUserOptionChange, isMulti: true }), _jsxs("div", { className: "panel__content__form__section__list__new-item__actions", children: [_jsx("button", { className: "panel__content__form__section__list__new-item__add-btn btn btn--dark service-editor__owner__action", disabled: isReadOnly ||
                                                                    ownerInputs.some((i) => owners.includes(i)), onClick: addOwner, tabIndex: -1, children: "Save" }), _jsx("button", { className: "panel__content__form__section__list__new-item__cancel-btn btn btn--dark service-editor__owner__action", disabled: isReadOnly, onClick: hideAddOrEditOwnerInput, tabIndex: -1, children: "Cancel" })] })] }))] }), owners.length < MINIMUM_SERVICE_OWNERS &&
                                        showOwnerEditInput !== true && (_jsxs("div", { className: "service-editor__owner__validation", title: `${MINIMUM_SERVICE_OWNERS} owners required`, children: [_jsx(ErrorIcon, {}), _jsxs("div", { className: "service-editor__owner__validation-label", children: ["Service requires at least ", MINIMUM_SERVICE_OWNERS, " owners"] })] })), showOwnerEditInput !== true && (_jsx("div", { className: "panel__content__form__section__list__new-item__add", children: _jsx("button", { className: "panel__content__form__section__list__new-item__add-btn btn btn--dark", disabled: isReadOnly, onClick: showAddOwnerInput, tabIndex: -1, title: "Add owner", children: "Add Value" }) }))] })] }))] }), _jsx(PanelForm, { children: _jsx(PanelFormValidatedTextField, { ref: patternRef, name: "MCP Server", isReadOnly: isReadOnly, className: "service-editor__pattern__input", errorMessageClassName: "service-editor__pattern__input", prompt: _jsx(_Fragment, { children: "To enable MCP access to this service, tag it to an MCP server" }), update: (value) => {
                        updateMcpServer(value);
                    }, validate: getMcpServerValidationMessage, value: mcpServer }) })] }));
});
export const ServiceEditor = observer(() => {
    const editorStore = useEditorStore();
    const serviceState = editorStore.tabManagerState.getCurrentEditorState(ServiceEditorState);
    const service = serviceState.service;
    const isReadOnly = serviceState.isReadOnly;
    const selectedTab = serviceState.selectedTab;
    const changeTab = (tab) => () => serviceState.setSelectedTab(tab);
    useApplicationNavigationContext(LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.SERVICE_EDITOR);
    const renderServiceEditorTab = () => {
        switch (selectedTab) {
            case SERVICE_TAB.GENERAL:
                return _jsx(ServiceGeneralEditor, {});
            case SERVICE_TAB.EXECUTION:
                return _jsx(ServiceExecutionEditor, {});
            case SERVICE_TAB.REGISTRATION:
                return _jsx(ServiceRegistrationEditor, {});
            case SERVICE_TAB.TEST:
                return (_jsx(ServiceTestableEditor, { serviceTestableState: serviceState.testableState }));
            case SERVICE_TAB.POST_VALIDATION:
                return (_jsx(ServicePostValidationsEditor, { validationState: serviceState.postValidationState }));
            default:
                return null;
        }
    };
    const renderTabDocLInk = (tab) => {
        let doc = null;
        switch (tab) {
            case SERVICE_TAB.TEST:
                doc =
                    LEGEND_STUDIO_DOCUMENTATION_KEY.QUESTION_HOW_TO_WRITE_A_SERVICE_TEST;
                break;
            case SERVICE_TAB.POST_VALIDATION:
                doc =
                    LEGEND_STUDIO_DOCUMENTATION_KEY.QUESTION_HOW_TO_WRITE_A_SERVICE_POST_VALIDATION;
                break;
            default:
                break;
        }
        return doc ? _jsx(DocumentationLink, { documentationKey: doc }) : null;
    };
    return (_jsx("div", { className: "service-editor", children: _jsxs("div", { className: "panel", children: [_jsx("div", { className: "panel__header", 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: "service" }), _jsx("div", { className: "panel__header__title__content", children: service.name })] }) }), _jsx("div", { className: "panel__header service-editor__header--with-tabs", children: _jsx("div", { className: "uml-element-editor__tabs", children: Object.values(SERVICE_TAB)
                            .filter((tab) => {
                            if (tab === SERVICE_TAB.REGISTRATION) {
                                return Boolean(editorStore.applicationStore.config.options
                                    .TEMPORARY__serviceRegistrationConfig.length);
                            }
                            return true;
                        })
                            .map((tab) => (_jsxs("div", { onClick: changeTab(tab), className: clsx('service-editor__tab', {
                                'service-editor__tab--active': tab === selectedTab,
                            }), children: [prettyCONSTName(tab), renderTabDocLInk(tab)] }, tab))) }) }), _jsx("div", { className: "panel__content service-editor__content", children: renderServiceEditorTab() })] }) }));
});
//# sourceMappingURL=ServiceEditor.js.map