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, { useEffect } from 'react';
import { observer } from 'mobx-react-lite';
import { ServicePureExecutionState } from '../../../../stores/editor/editor-state/element-editor-state/service/ServiceExecutionState.js';
import { Dialog, PanelLoadingIndicator, PlayIcon, ControlledDropdownMenu, MenuContent, CaretDownIcon, MenuContentItem, PauseCircleIcon, PencilIcon, Modal, ModalBody, ModalFooter, ModalFooterButton, ModalHeader, } from '@finos/legend-art';
import { assertErrorThrown, guaranteeNonNullable, returnUndefOnError, } from '@finos/legend-shared';
import { flowResult } from 'mobx';
import { useEditorStore } from '../../EditorStoreProvider.js';
import { KeyedExecutionParameter, MultiExecutionParameters, PureExecution, } from '@finos/legend-graph';
import { ServiceQueryBuilderState, LambdaParameterValuesEditor, QueryBuilderTextEditorMode, QueryLoaderDialog, ExecutionPlanViewer, QueryBuilderAdvancedWorkflowState, QueryBuilderActionConfig, LineageViewer, } from '@finos/legend-query-builder';
import { ProjectViewerEditorMode } from '../../../../stores/project-view/ProjectViewerEditorMode.js';
import { useLegendStudioApplicationStore } from '../../../LegendStudioFrameworkProvider.js';
import { SNAPSHOT_ALIAS, SNAPSHOT_VERSION_ALIAS, } from '@finos/legend-server-depot';
import { CODE_EDITOR_LANGUAGE } from '@finos/legend-code-editor';
import { CodeEditor } from '@finos/legend-lego/code-editor';
import { EXTERNAL_APPLICATION_NAVIGATION__generateServiceQueryCreatorUrl } from '../../../../__lib__/LegendStudioNavigation.js';
import { pureExecution_setFunction } from '../../../../stores/graph-modifier/DSL_Service_GraphModifierHelper.js';
import { ServiceEditorState } from '../../../../stores/editor/editor-state/element-editor-state/service/ServiceEditorState.js';
const ServiceExecutionResultViewer = observer((props) => {
    const { executionState } = props;
    const applicationStore = executionState.editorStore.applicationStore;
    // execution
    const executionResultText = executionState.executionResultText;
    const closeExecutionResultViewer = () => executionState.setExecutionResultText(undefined);
    return (_jsx(Dialog, { open: Boolean(executionResultText), onClose: closeExecutionResultViewer, classes: {
            root: 'editor-modal__root-container',
            container: 'editor-modal__container',
            paper: 'editor-modal__content',
        }, children: _jsxs(Modal, { darkMode: !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled, className: "editor-modal", children: [_jsx(ModalHeader, { title: "Execution Result" }), _jsx(ModalBody, { children: _jsx(CodeEditor, { inputValue: executionResultText ?? '', isReadOnly: true, language: CODE_EDITOR_LANGUAGE.JSON }) }), _jsx(ModalFooter, { children: _jsx(ModalFooterButton, { className: "modal__footer__close-btn", onClick: closeExecutionResultViewer, text: "Close", type: "secondary" }) })] }) }));
});
export const ServiceExecutionQueryEditor = observer((props) => {
    const { executionState, isReadOnly } = props;
    const applicationStore = useLegendStudioApplicationStore();
    const editorStore = useEditorStore();
    const queryState = executionState.queryState;
    const embeddedQueryBuilderState = editorStore.embeddedQueryBuilderState;
    const service = executionState.serviceEditorState.service;
    // actions
    const editWithQueryBuilder = (openInTextMode = false) => applicationStore.guardUnhandledError(async () => {
        const selectedExecutionState = executionState.selectedExecutionContextState;
        await flowResult(embeddedQueryBuilderState.setEmbeddedQueryBuilderConfiguration({
            setupQueryBuilderState: async () => {
                const sourceInfo = {
                    service: service.path,
                    ...editorStore.editorMode.getSourceInfo(),
                };
                const queryBuilderState = new ServiceQueryBuilderState(embeddedQueryBuilderState.editorStore.applicationStore, embeddedQueryBuilderState.editorStore.graphManagerState, QueryBuilderAdvancedWorkflowState.INSTANCE, QueryBuilderActionConfig.INSTANCE, service, undefined, selectedExecutionState?.executionContext instanceof
                    KeyedExecutionParameter
                    ? selectedExecutionState.executionContext.key
                    : undefined, undefined, undefined, embeddedQueryBuilderState.editorStore.applicationStore.config.options.queryBuilderConfig, sourceInfo);
                queryBuilderState.initializeWithQuery(executionState.execution.func);
                if (openInTextMode) {
                    queryBuilderState.textEditorState.openModal(QueryBuilderTextEditorMode.TEXT);
                }
                return queryBuilderState;
            },
            actionConfigs: [
                {
                    key: 'save-query-btn',
                    renderer: (queryBuilderState) => {
                        const save = applicationStore.guardUnhandledError(async () => {
                            try {
                                const rawLambda = queryBuilderState.buildQuery();
                                await flowResult(executionState.queryState.updateLamba(rawLambda));
                                applicationStore.notificationService.notifySuccess(`Service query is updated`);
                                embeddedQueryBuilderState.setEmbeddedQueryBuilderConfiguration(undefined);
                            }
                            catch (error) {
                                assertErrorThrown(error);
                                applicationStore.notificationService.notifyError(`Can't save query: ${error.message}`);
                            }
                        });
                        return (_jsx("button", { className: "query-builder__dialog__header__custom-action", tabIndex: -1, disabled: isReadOnly, onClick: save, children: "Save Query" }));
                    },
                },
            ],
            disableCompile: true,
        }));
        executionState.setOpeningQueryEditor(false);
    });
    const importQuery = () => queryState.queryLoaderState.setQueryLoaderDialogOpen(true);
    const runQuery = applicationStore.guardUnhandledError(() => flowResult(executionState.handleRunQuery()));
    const executionIsRunning = executionState.isRunningQuery || executionState.isGeneratingPlan;
    const cancelQuery = applicationStore.guardUnhandledError(() => flowResult(executionState.cancelQuery()));
    const generatePlan = applicationStore.guardUnhandledError(() => flowResult(executionState.generatePlan(false)));
    const generateLineage = applicationStore.guardUnhandledError(() => flowResult(executionState.generateLineage()));
    const debugPlanGeneration = applicationStore.guardUnhandledError(() => flowResult(executionState.generatePlan(true)));
    const openServiceCubeViewer = editorStore.applicationStore.guardUnhandledError(async () => {
        await executionState.handleOpeningDataCube(service, editorStore);
    });
    const openQueryInLegendQuery = () => {
        if (!applicationStore.config.queryApplicationUrl) {
            return;
        }
        let projectGAV;
        if (editorStore.editorMode instanceof ProjectViewerEditorMode) {
            const viewerEditorMode = editorStore.editorMode;
            // for Achive mode
            if (viewerEditorMode.viewerStore.projectGAVCoordinates) {
                projectGAV = viewerEditorMode.viewerStore.projectGAVCoordinates;
            }
            else {
                // for other viewer modes, if no version we use project `HEAD`
                projectGAV = {
                    groupId: editorStore.projectConfigurationEditorState
                        .currentProjectConfiguration.groupId,
                    artifactId: editorStore.projectConfigurationEditorState
                        .currentProjectConfiguration.artifactId,
                    versionId: viewerEditorMode.viewerStore.version?.id.id ??
                        SNAPSHOT_VERSION_ALIAS,
                };
            }
        }
        else {
            const currentWorkSpaceId = editorStore.sdlcState.currentWorkspace?.workspaceId;
            projectGAV = {
                groupId: editorStore.projectConfigurationEditorState
                    .currentProjectConfiguration.groupId,
                artifactId: editorStore.projectConfigurationEditorState
                    .currentProjectConfiguration.artifactId,
                versionId: editorStore.sdlcState.projectPublishedVersions.includes(`${currentWorkSpaceId}-${SNAPSHOT_ALIAS}`)
                    ? `${currentWorkSpaceId}-${SNAPSHOT_ALIAS}`
                    : SNAPSHOT_VERSION_ALIAS,
            };
        }
        applicationStore.navigationService.navigator.visitAddress(EXTERNAL_APPLICATION_NAVIGATION__generateServiceQueryCreatorUrl(applicationStore.config.queryApplicationUrl, projectGAV.groupId, projectGAV.artifactId, projectGAV.versionId, service.path));
    };
    // convert to string
    useEffect(() => {
        flowResult(queryState.convertLambdaObjectToGrammarString({ pretty: true })).catch(applicationStore.alertUnhandledError);
    }, [applicationStore, queryState]);
    return (_jsxs("div", { className: "panel service-execution-query-editor", children: [_jsxs("div", { className: "panel__header", children: [_jsx("div", { className: "panel__header__title", children: _jsx("div", { className: "panel__header__title__label service-editor__execution__label--query", children: "query" }) }), _jsxs("div", { className: "panel__header__actions", children: [_jsxs("div", { className: "btn__dropdown-combo btn__dropdown-combo--primary", children: [_jsxs("button", { className: "btn__dropdown-combo__label", onClick: editWithQueryBuilder(), title: "Edit Query", tabIndex: -1, children: [_jsx(PencilIcon, { className: "btn__dropdown-combo__label__icon" }), _jsx("div", { className: "btn__dropdown-combo__label__title", children: "Edit Query" })] }), _jsx(ControlledDropdownMenu, { className: "btn__dropdown-combo__dropdown-btn", content: _jsx(MenuContent, { children: _jsx(MenuContentItem, { className: "btn__dropdown-combo__option", onClick: editWithQueryBuilder(true), children: "Text Mode" }) }), menuProps: {
                                            anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
                                            transformOrigin: { vertical: 'top', horizontal: 'right' },
                                        }, children: _jsx(CaretDownIcon, {}) })] }), _jsx("div", { className: "btn__dropdown-combo btn__dropdown-combo--primary", children: executionState.isRunningQuery ? (_jsx("button", { className: "btn__dropdown-combo__canceler", onClick: cancelQuery, tabIndex: -1, children: _jsxs("div", { className: "btn--dark btn--caution btn__dropdown-combo__canceler__label", children: [_jsx(PauseCircleIcon, { className: "btn__dropdown-combo__canceler__label__icon" }), _jsx("div", { className: "btn__dropdown-combo__canceler__label__title", children: "Stop" })] }) })) : (_jsxs(_Fragment, { children: [_jsxs("button", { className: "btn__dropdown-combo__label", onClick: runQuery, title: "Run Query", disabled: executionIsRunning, tabIndex: -1, children: [_jsx(PlayIcon, { className: "btn__dropdown-combo__label__icon" }), _jsx("div", { className: "btn__dropdown-combo__label__title", children: "Run Query" })] }), _jsx(ControlledDropdownMenu, { className: "btn__dropdown-combo__dropdown-btn", disabled: executionIsRunning, content: _jsxs(MenuContent, { children: [_jsx(MenuContentItem, { className: "btn__dropdown-combo__option", onClick: generatePlan, children: "Generate Plan" }), _jsx(MenuContentItem, { className: "btn__dropdown-combo__option", onClick: generateLineage, children: "View Lineage" }), _jsx(MenuContentItem, { className: "btn__dropdown-combo__option", onClick: debugPlanGeneration, children: "Debug" })] }), menuProps: {
                                                anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
                                                transformOrigin: { vertical: 'top', horizontal: 'right' },
                                            }, children: _jsx(CaretDownIcon, {}) })] })) }), _jsx("div", { className: "btn__dropdown-combo btn__dropdown-combo--primary", children: _jsx("button", { className: "btn__dropdown-combo__label", onClick: openServiceCubeViewer, title: "Data Cube (BETA)", disabled: executionIsRunning, tabIndex: -1, children: _jsx("div", { className: "btn__dropdown-combo__label__title", children: "Data Cube" }) }) }), _jsxs(ControlledDropdownMenu, { className: "btn__dropdown-combo", disabled: executionIsRunning, content: _jsxs(MenuContent, { children: [_jsx(MenuContentItem, { className: "btn__dropdown-combo__option", onClick: importQuery, children: "Import Query" }), _jsx(MenuContentItem, { className: "btn__dropdown-combo__option", onClick: openQueryInLegendQuery, disabled: !applicationStore.config.queryApplicationUrl, children: "Create an Ad-hoc Query" })] }), menuProps: {
                                    anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
                                    transformOrigin: { vertical: 'top', horizontal: 'right' },
                                }, children: [_jsx("div", { className: "btn__dropdown-combo__label", children: _jsx("div", { className: "btn__dropdown-combo__label__title", children: "Advanced" }) }), _jsx("div", { className: "btn__dropdown-combo__dropdown-btn", children: _jsx(CaretDownIcon, {}) })] })] })] }), _jsxs("div", { className: "panel__content property-mapping-editor__entry__container", children: [_jsx(PanelLoadingIndicator, { isLoading: executionState.isOpeningQueryEditor || executionIsRunning }), _jsx("div", { className: "service-execution-query-editor__content", children: _jsx(CodeEditor, { inputValue: queryState.lambdaString, isReadOnly: true, language: CODE_EDITOR_LANGUAGE.PURE }) }), queryState.queryLoaderState.isQueryLoaderDialogOpen && (_jsx(QueryLoaderDialog, { queryLoaderState: queryState.queryLoaderState, title: "import query" })), _jsx(ExecutionPlanViewer, { executionPlanState: executionState.executionPlanState }), _jsx(LineageViewer, { lineageState: executionState.lineageState }), _jsx(ServiceExecutionResultViewer, { executionState: executionState }), executionState.parametersState.parameterValuesEditorState
                        .showModal && (_jsx(LambdaParameterValuesEditor, { graph: executionState.editorStore.graphManagerState.graph, observerContext: executionState.editorStore.changeDetectionState.observerContext, lambdaParametersState: executionState.parametersState }))] })] }));
});
export const queryService = async (service, editorStore) => {
    const embeddedQueryBuilderState = editorStore.embeddedQueryBuilderState;
    const applicationStore = editorStore.applicationStore;
    const execution = service.execution instanceof PureExecution ? service.execution : undefined;
    const selectedExec = execution instanceof MultiExecutionParameters
        ? execution.singleExecutionParameters[0]?.key
        : undefined;
    const sourceInfo = {
        service: service.path,
        ...editorStore.editorMode.getSourceInfo(),
    };
    await flowResult(embeddedQueryBuilderState.setEmbeddedQueryBuilderConfiguration({
        setupQueryBuilderState: async () => {
            const queryBuilderState = new ServiceQueryBuilderState(embeddedQueryBuilderState.editorStore.applicationStore, embeddedQueryBuilderState.editorStore.graphManagerState, QueryBuilderAdvancedWorkflowState.INSTANCE, QueryBuilderActionConfig.INSTANCE, service, undefined, selectedExec, undefined, undefined, embeddedQueryBuilderState.editorStore.applicationStore.config.options.queryBuilderConfig, sourceInfo);
            if (execution) {
                queryBuilderState.initializeWithQuery(execution.func);
            }
            return queryBuilderState;
        },
        actionConfigs: [
            {
                key: 'save-query-btn',
                renderer: (queryBuilderState) => {
                    const save = applicationStore.guardUnhandledError(async () => {
                        try {
                            const rawLambda = queryBuilderState.buildQuery();
                            const serviceState = returnUndefOnError(() => editorStore.tabManagerState.getCurrentEditorState(ServiceEditorState));
                            if (serviceState?.service === service &&
                                serviceState.executionState instanceof
                                    ServicePureExecutionState) {
                                await flowResult(serviceState.executionState.queryState.updateLamba(rawLambda));
                            }
                            else {
                                pureExecution_setFunction(guaranteeNonNullable(execution, 'Service execution expected to be a pure execution'), rawLambda);
                            }
                            applicationStore.notificationService.notifySuccess(`Service query is updated`);
                            embeddedQueryBuilderState.setEmbeddedQueryBuilderConfiguration(undefined);
                        }
                        catch (error) {
                            assertErrorThrown(error);
                            applicationStore.notificationService.notifyError(`Can't save query: ${error.message}`);
                        }
                    });
                    return (_jsx("button", { className: "query-builder__dialog__header__custom-action", tabIndex: -1, disabled: editorStore.disableGraphEditing, onClick: save, children: "Save Query" }));
                },
            },
        ],
    }));
};
//# sourceMappingURL=ServiceExecutionQueryEditor.js.map