/**
 * 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 { observable, action, flow, makeObservable, flowResult } from 'mobx';
import { assertErrorThrown, LogEvent, stringifyLosslessJSON, UnsupportedOperationError, filterByType, guaranteeNonNullable, StopWatch, } from '@finos/legend-shared';
import { decorateRuntimeWithNewMapping, RuntimeEditorState, } from '../../../editor-state/element-editor-state/RuntimeEditorState.js';
import { PureSingleExecution, PureMultiExecution, KeyedExecutionParameter, GRAPH_MANAGER_EVENT, RawLambda, EngineRuntime, RuntimePointer, PackageableElementExplicitReference, buildSourceInformationSourceId, QueryProjectCoordinates, buildLambdaVariableExpressions, observe_ValueSpecification, VariableExpression, stub_PackageableRuntime, stub_Mapping, reportGraphAnalytics, QuerySearchSpecification, } from '@finos/legend-graph';
import { parseGACoordinates } from '@finos/legend-storage';
import { runtime_addMapping } from '../../../../graph-modifier/DSL_Mapping_GraphModifierHelper.js';
import { keyedExecutionParameter_setKey, pureExecution_setFunction, pureMultiExecution_addExecutionParameter, pureMultiExecution_deleteExecutionParameter, pureMultiExecution_setExecutionKey, pureSingleExecution_setMapping, pureSingleExecution_setRuntime, service_setExecution, } from '../../../../graph-modifier/DSL_Service_GraphModifierHelper.js';
import { buildExecutionParameterValues, getExecutionQueryFromRawLambda, LambdaEditorState, LambdaParametersState, LambdaParameterState, PARAMETER_SUBMIT_ACTION, QueryBuilderTelemetryHelper, QueryLoaderState, QUERY_BUILDER_EVENT, ExecutionPlanState, QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT, getRawLambdaForLetFuncs, LineageState, } from '@finos/legend-query-builder';
import { DEFAULT_TAB_SIZE } from '@finos/legend-application';
import { openDataCube } from '../../../data-cube/LegendStudioDataCubeHelper.js';
export class ServiceExecutionParametersState extends LambdaParametersState {
    executionState;
    constructor(executionState) {
        super();
        makeObservable(this, {
            parameterValuesEditorState: observable,
            parameterStates: observable,
            addParameter: action,
            removeParameter: action,
            openModal: action,
            build: action,
            setParameters: action,
        });
        this.executionState = executionState;
    }
    openModal(query) {
        this.parameterStates = this.build(query);
        this.parameterValuesEditorState.open(() => flowResult(this.executionState.runQuery()).catch(this.executionState.editorStore.applicationStore.alertUnhandledError), PARAMETER_SUBMIT_ACTION.RUN);
    }
    openDataCubeModal(query, element, editorStore) {
        this.parameterStates = this.build(query);
        this.parameterValuesEditorState.open(() => this.executionState
            .openingDataCube(element, editorStore)
            .catch(this.executionState.editorStore.applicationStore
            .alertUnhandledError), PARAMETER_SUBMIT_ACTION.RUN);
    }
    build(query) {
        const parameters = buildLambdaVariableExpressions(query, this.executionState.editorStore.graphManagerState)
            .map((p) => observe_ValueSpecification(p, this.executionState.editorStore.changeDetectionState.observerContext))
            .filter(filterByType(VariableExpression));
        const states = parameters.map((p) => {
            const parmeterState = new LambdaParameterState(p, this.executionState.editorStore.changeDetectionState.observerContext, this.executionState.editorStore.graphManagerState.graph);
            parmeterState.mockParameterValue();
            return parmeterState;
        });
        return states;
    }
}
export class ServiceExecutionState {
    editorStore;
    serviceEditorState;
    execution;
    constructor(editorStore, serviceEditorState, execution) {
        makeObservable(this, {
            execution: observable,
        });
        this.editorStore = editorStore;
        this.execution = execution;
        this.serviceEditorState = serviceEditorState;
    }
}
export class UnsupportedServiceExecutionState extends ServiceExecutionState {
    get serviceExecutionParameters() {
        return undefined;
    }
}
const decorateSearchSpecificationForServiceQueryImporter = (val, editorStore) => {
    const currentProjectCoordinates = new QueryProjectCoordinates();
    currentProjectCoordinates.groupId =
        editorStore.projectConfigurationEditorState.currentProjectConfiguration.groupId;
    currentProjectCoordinates.artifactId =
        editorStore.projectConfigurationEditorState.currentProjectConfiguration.artifactId;
    val.projectCoordinates = [
        // either get queries for the current project
        currentProjectCoordinates,
        // or any of its dependencies
        ...Array.from(editorStore.graphManagerState.graph.dependencyManager.projectDependencyModelsIndex.keys()).map((dependencyKey) => {
            const { groupId, artifactId } = parseGACoordinates(dependencyKey);
            const coordinates = new QueryProjectCoordinates();
            coordinates.groupId = groupId;
            coordinates.artifactId = artifactId;
            return coordinates;
        }),
    ];
    return val;
};
export class ServicePureExecutionQueryState extends LambdaEditorState {
    editorStore;
    queryLoaderState;
    execution;
    isInitializingLambda = false;
    constructor(editorStore, execution) {
        super('', '');
        makeObservable(this, {
            execution: observable,
            isInitializingLambda: observable,
            setIsInitializingLambda: action,
            setLambda: action,
            updateLamba: flow,
            importQuery: flow,
        });
        this.editorStore = editorStore;
        this.execution = execution;
        this.queryLoaderState = new QueryLoaderState(editorStore.applicationStore, editorStore.graphManagerState.graphManager, {
            loadQuery: (query) => {
                flowResult(this.importQuery(query.id)).catch(this.editorStore.applicationStore.alertUnhandledError);
            },
            decorateSearchSpecification: (val) => decorateSearchSpecificationForServiceQueryImporter(val, this.editorStore),
            fetchDefaultQueries: async () => {
                const searchSpecification = new QuerySearchSpecification();
                searchSpecification.limit = QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT;
                return this.editorStore.graphManagerState.graphManager.searchQueries(decorateSearchSpecificationForServiceQueryImporter(searchSpecification, this.editorStore));
            },
            isReadOnly: true,
        });
    }
    get lambdaId() {
        return buildSourceInformationSourceId([
            this.execution._OWNER.path,
            'execution',
        ]);
    }
    get query() {
        return this.execution.func;
    }
    setIsInitializingLambda(val) {
        this.isInitializingLambda = val;
    }
    setLambda(val) {
        pureExecution_setFunction(this.execution, val);
    }
    *importQuery(selectedQueryID) {
        try {
            const content = (yield this.editorStore.graphManagerState.graphManager.prettyLambdaContent((yield this.editorStore.graphManagerState.graphManager.getQueryInfo(selectedQueryID)).content));
            const lambda = (yield this.editorStore.graphManagerState.graphManager.pureCodeToLambda(content));
            yield flowResult(this.updateLamba(lambda));
        }
        catch (error) {
            assertErrorThrown(error);
            this.editorStore.applicationStore.notificationService.notifyError(error);
        }
        finally {
            this.queryLoaderState.setQueryLoaderDialogOpen(false);
        }
    }
    *updateLamba(val) {
        this.setLambda(val);
        yield flowResult(this.convertLambdaObjectToGrammarString({ pretty: true }));
    }
    *convertLambdaObjectToGrammarString(options) {
        if (this.execution.func.body) {
            try {
                const lambdas = new Map();
                lambdas.set(this.lambdaId, new RawLambda(this.execution.func.parameters, this.execution.func.body));
                const isolatedLambdas = (yield this.editorStore.graphManagerState.graphManager.lambdasToPureCode(lambdas, options?.pretty));
                const grammarText = isolatedLambdas.get(this.lambdaId);
                this.setLambdaString(grammarText !== undefined
                    ? this.extractLambdaString(grammarText)
                    : '');
                this.clearErrors();
            }
            catch (error) {
                assertErrorThrown(error);
                this.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.PARSING_FAILURE), error);
            }
        }
        else {
            this.clearErrors();
            this.setLambdaString('');
        }
    }
    // NOTE: since we don't allow edition in text mode, we don't need to implement this
    *convertLambdaGrammarStringToObject() {
        throw new UnsupportedOperationError();
    }
}
export class ServiceExecutionContextState {
    executionState;
    constructor(executionState) {
        this.executionState = executionState;
    }
}
export class SingleExecutionContextState extends ServiceExecutionContextState {
    constructor(executionState) {
        super(executionState);
        makeObservable(this, {
            setMapping: action,
            setRuntime: action,
        });
        this.executionState = executionState;
    }
    setMapping(value) {
        pureSingleExecution_setMapping(this.executionState.execution, value, this.executionState.editorStore.changeDetectionState.observerContext);
    }
    setRuntime(value) {
        pureSingleExecution_setRuntime(this.executionState.execution, value, this.executionState.editorStore.changeDetectionState.observerContext);
    }
    get executionContext() {
        return {
            mapping: guaranteeNonNullable(this.executionState.execution.mapping),
            runtime: guaranteeNonNullable(this.executionState.execution.runtime),
        };
    }
}
export class KeyedExecutionContextState extends ServiceExecutionContextState {
    keyedExecutionParameter;
    constructor(keyedExecutionParameter, executionState) {
        super(executionState);
        makeObservable(this, {
            setMapping: action,
            setRuntime: action,
        });
        this.keyedExecutionParameter = keyedExecutionParameter;
    }
    setMapping(value) {
        pureSingleExecution_setMapping(this.keyedExecutionParameter, value, this.executionState.editorStore.changeDetectionState.observerContext);
    }
    setRuntime(value) {
        pureSingleExecution_setRuntime(this.keyedExecutionParameter, value, this.executionState.editorStore.changeDetectionState.observerContext);
    }
    get executionContext() {
        return this.keyedExecutionParameter;
    }
}
export class ServicePureExecutionState extends ServiceExecutionState {
    queryState;
    selectedExecutionContextState;
    runtimeEditorState;
    isOpeningQueryEditor = false;
    showChangeExecModal = false;
    isRunningQuery = false;
    isGeneratingPlan = false;
    isGeneratingLineage = false;
    executionResultText; // NOTE: stored as lossless JSON string
    executionPlanState;
    parametersState;
    queryRunPromise = undefined;
    lineageState;
    constructor(editorStore, serviceEditorState, execution) {
        super(editorStore, serviceEditorState, execution);
        makeObservable(this, {
            cancelQuery: flow,
            generateLineage: flow,
            isGeneratingLineage: observable,
        });
        this.execution = execution;
        this.queryState = new ServicePureExecutionQueryState(this.editorStore, execution);
        this.executionPlanState = new ExecutionPlanState(this.editorStore.applicationStore, this.editorStore.graphManagerState);
        this.parametersState = new ServiceExecutionParametersState(this);
        this.lineageState = new LineageState(this.editorStore.applicationStore);
    }
    isChangeExecutionDisabled() {
        return false;
    }
    setIsRunningQuery(val) {
        this.isRunningQuery = val;
    }
    setShowChangeExecModal(val) {
        this.showChangeExecModal = val;
    }
    setOpeningQueryEditor(val) {
        this.isOpeningQueryEditor = val;
    }
    setExecutionResultText = (executionResult) => {
        this.executionResultText = executionResult;
    };
    setQueryState = (queryState) => {
        this.queryState = queryState;
    };
    setQueryRunPromise = (promise) => {
        this.queryRunPromise = promise;
    };
    async handleOpeningDataCube(element, editorStore) {
        const query = this.queryState.query;
        const parameters = (query.parameters ?? []);
        if (parameters.length) {
            this.parametersState.openDataCubeModal(query, element, editorStore);
        }
        else {
            await openDataCube(element, editorStore);
        }
    }
    async openingDataCube(element, editorStore) {
        const params = buildExecutionParameterValues(this.parametersState.parameterStates, this.editorStore.graphManagerState);
        const letFuncsRawLambda = getRawLambdaForLetFuncs(this.parametersState.parameterStates, this.editorStore.graphManagerState);
        await openDataCube(element, editorStore, params, letFuncsRawLambda);
    }
    *generatePlan(debug) {
        if (this.isGeneratingPlan) {
            return;
        }
        try {
            const query = this.queryState.query;
            this.isGeneratingPlan = true;
            let rawPlan;
            const stopWatch = new StopWatch();
            const report = reportGraphAnalytics(this.editorStore.graphManagerState.graph);
            if (debug) {
                QueryBuilderTelemetryHelper.logEvent_ExecutionPlanDebugLaunched(this.editorStore.applicationStore.telemetryService);
                const debugResult = (yield this.editorStore.graphManagerState.graphManager.debugExecutionPlanGeneration(query, this.selectedExecutionContextState?.executionContext.mapping.value, this.selectedExecutionContextState?.executionContext.runtime, this.editorStore.graphManagerState.graph, undefined, report));
                rawPlan = debugResult.plan;
                this.executionPlanState.setDebugText(debugResult.debug);
            }
            else {
                QueryBuilderTelemetryHelper.logEvent_ExecutionPlanGenerationLaunched(this.editorStore.applicationStore.telemetryService);
                rawPlan =
                    (yield this.editorStore.graphManagerState.graphManager.generateExecutionPlan(query, this.selectedExecutionContextState?.executionContext.mapping.value, this.selectedExecutionContextState?.executionContext.runtime, this.editorStore.graphManagerState.graph, undefined, report));
            }
            stopWatch.record();
            try {
                this.executionPlanState.setRawPlan(rawPlan);
                const plan = this.editorStore.graphManagerState.graphManager.buildExecutionPlan(rawPlan, this.editorStore.graphManagerState.graph);
                this.executionPlanState.initialize(plan);
            }
            catch {
                // do nothing
            }
            stopWatch.record(QUERY_BUILDER_EVENT.BUILD_EXECUTION_PLAN__SUCCESS);
            // report
            report.timings =
                this.editorStore.applicationStore.timeService.finalizeTimingsRecord(stopWatch, report.timings);
            if (debug) {
                QueryBuilderTelemetryHelper.logEvent_ExecutionPlanDebugSucceeded(this.editorStore.applicationStore.telemetryService, report);
            }
            else {
                QueryBuilderTelemetryHelper.logEvent_ExecutionPlanGenerationSucceeded(this.editorStore.applicationStore.telemetryService, report);
            }
        }
        catch (error) {
            assertErrorThrown(error);
            this.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.EXECUTION_FAILURE), error);
            this.editorStore.applicationStore.notificationService.notifyError(error);
        }
        finally {
            this.isGeneratingPlan = false;
        }
    }
    *handleRunQuery() {
        if (this.isRunningQuery) {
            return;
        }
        const query = this.queryState.query;
        const parameters = (query.parameters ?? []);
        if (parameters.length) {
            this.parametersState.openModal(query);
        }
        else {
            this.runQuery();
        }
    }
    *runQuery() {
        if (this.isRunningQuery) {
            return;
        }
        QueryBuilderTelemetryHelper.logEvent_QueryRunLaunched(this.editorStore.applicationStore.telemetryService);
        let promise;
        try {
            this.isRunningQuery = true;
            const stopWatch = new StopWatch();
            const report = reportGraphAnalytics(this.editorStore.graphManagerState.graph);
            promise = this.editorStore.graphManagerState.graphManager.runQuery(getExecutionQueryFromRawLambda(this.queryState.query, this.parametersState.parameterStates, this.editorStore.graphManagerState), this.selectedExecutionContextState?.executionContext.mapping.value, this.selectedExecutionContextState?.executionContext.runtime, this.editorStore.graphManagerState.graph, {
                useLosslessParse: true,
                parameterValues: buildExecutionParameterValues(this.parametersState.parameterStates, this.editorStore.graphManagerState),
            }, report);
            this.setQueryRunPromise(promise);
            const result = (yield promise);
            if (this.queryRunPromise === promise) {
                this.setExecutionResultText(stringifyLosslessJSON(result.executionResult, undefined, DEFAULT_TAB_SIZE));
                this.parametersState.setParameters([]);
                // report
                report.timings =
                    this.editorStore.applicationStore.timeService.finalizeTimingsRecord(stopWatch, report.timings);
                QueryBuilderTelemetryHelper.logEvent_QueryRunSucceeded(this.editorStore.applicationStore.telemetryService, report);
            }
        }
        catch (error) {
            // When user cancels the query by calling the cancelQuery api, it will throw an execution failure error.
            // For now, we don't want to notify users about this failure. Therefore we check to ensure the promise is still the same one.
            // When cancelled the query, we set the queryRunPromise as undefined.
            if (this.queryRunPromise === promise) {
                assertErrorThrown(error);
                this.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.EXECUTION_FAILURE), error);
                this.editorStore.applicationStore.notificationService.notifyError(error);
            }
        }
        finally {
            this.isRunningQuery = false;
        }
    }
    *cancelQuery() {
        this.setIsRunningQuery(false);
        this.setQueryRunPromise(undefined);
        try {
            yield this.editorStore.graphManagerState.graphManager.cancelUserExecutions(true);
        }
        catch (error) {
            // Don't notify users about success or failure
            this.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.EXECUTION_FAILURE), error);
        }
    }
    *generateLineage() {
        if (this.isGeneratingLineage) {
            return;
        }
        try {
            this.isGeneratingLineage = true;
            const query = this.queryState.query;
            const mapping = this.selectedExecutionContextState?.executionContext.mapping.value;
            const lineageRawData = (yield this.editorStore.graphManagerState.graphManager.generateLineage(query, mapping, undefined, this.editorStore.graphManagerState.graph, undefined));
            const lineageData = this.editorStore.graphManagerState.graphManager.buildLineage(lineageRawData);
            this.lineageState.setLineageData(lineageData);
        }
        catch (error) {
            assertErrorThrown(error);
            this.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.LINEAGE_GENERATION_FAILURE), error);
            this.editorStore.applicationStore.notificationService.notifyError(error);
        }
        finally {
            this.isGeneratingLineage = false;
        }
    }
    get serviceExecutionParameters() {
        if (!this.selectedExecutionContextState || this.isRunningQuery) {
            return undefined;
        }
        const query = this.queryState.query;
        return {
            query,
            mapping: this.selectedExecutionContextState.executionContext.mapping.value,
            runtime: this.selectedExecutionContextState.executionContext.runtime,
        };
    }
    closeRuntimeEditor() {
        this.runtimeEditorState = undefined;
    }
    openRuntimeEditor() {
        if (this.selectedExecutionContextState &&
            !(this.selectedExecutionContextState.executionContext.runtime instanceof
                RuntimePointer)) {
            this.runtimeEditorState = new RuntimeEditorState(this.editorStore, this.selectedExecutionContextState.executionContext.runtime, true);
        }
    }
    useCustomRuntime() {
        const customRuntime = new EngineRuntime();
        guaranteeNonNullable(this.selectedExecutionContextState);
        const executionState = this
            .selectedExecutionContextState;
        runtime_addMapping(customRuntime, PackageableElementExplicitReference.create(executionState.executionContext.mapping.value));
        decorateRuntimeWithNewMapping(customRuntime, executionState.executionContext.mapping.value, this.editorStore);
        executionState.setRuntime(customRuntime);
    }
    autoSelectRuntimeOnMappingChange(mapping) {
        if (this.selectedExecutionContextState) {
            const runtimes = this.editorStore.graphManagerState.graph.ownRuntimes.filter((runtime) => runtime.runtimeValue.mappings.map((m) => m.value).includes(mapping));
            if (runtimes.length) {
                this.selectedExecutionContextState.setRuntime(runtimes[0].runtimeValue);
            }
            else {
                this.useCustomRuntime();
            }
        }
    }
    updateExecutionQuery() {
        pureExecution_setFunction(this.execution, this.queryState.query);
    }
}
export class InlineServicePureExecutionState extends ServicePureExecutionState {
    constructor(editorStore, serviceEditorState, execution) {
        super(editorStore, serviceEditorState, execution);
        makeObservable(this, {
            queryState: observable,
            isRunningQuery: observable,
            isGeneratingPlan: observable,
            isOpeningQueryEditor: observable,
            executionResultText: observable,
            executionPlanState: observable,
            showChangeExecModal: observable,
            setExecutionResultText: action,
            setQueryState: action,
            updateExecutionQuery: action,
            setOpeningQueryEditor: action,
            generatePlan: flow,
            handleRunQuery: flow,
            runQuery: flow,
        });
        this.selectedExecutionContextState =
            this.getInitiallySelectedExecutionContextState();
    }
    changeExecution() {
        throw new Error('Method not implemented.');
    }
    getInitiallySelectedExecutionContextState() {
        return undefined;
    }
}
export class SingleServicePureExecutionState extends ServicePureExecutionState {
    multiExecutionKey = 'key';
    constructor(editorStore, serviceEditorState, execution) {
        super(editorStore, serviceEditorState, execution);
        makeObservable(this, {
            queryState: observable,
            getInitiallySelectedExecutionContextState: observable,
            selectedExecutionContextState: observable,
            runtimeEditorState: observable,
            isRunningQuery: observable,
            isGeneratingPlan: observable,
            isOpeningQueryEditor: observable,
            executionResultText: observable,
            executionPlanState: observable,
            showChangeExecModal: observable,
            multiExecutionKey: observable,
            setExecutionResultText: action,
            closeRuntimeEditor: action,
            openRuntimeEditor: action,
            useCustomRuntime: action,
            setQueryState: action,
            autoSelectRuntimeOnMappingChange: action,
            updateExecutionQuery: action,
            setOpeningQueryEditor: action,
            changeExecution: action,
            setMultiExecutionKey: action,
            setShowChangeExecModal: action,
            setIsRunningQuery: action,
            generatePlan: flow,
            handleRunQuery: flow,
            runQuery: flow,
        });
        this.selectedExecutionContextState =
            this.getInitiallySelectedExecutionContextState();
    }
    isChangeExecutionDisabled() {
        return this.multiExecutionKey === '';
    }
    getInitiallySelectedExecutionContextState() {
        return new SingleExecutionContextState(this);
    }
    setMultiExecutionKey(val) {
        this.multiExecutionKey = val;
    }
    changeExecution() {
        if (this.execution.mapping && this.execution.runtime) {
            const _execution = new PureMultiExecution(this.multiExecutionKey, this.execution.func, this.serviceEditorState.service);
            const _parameter = new KeyedExecutionParameter(`execContext_1`, this.execution.mapping, this.execution.runtime);
            _execution.executionParameters = [_parameter];
            service_setExecution(this.serviceEditorState.service, _execution, this.editorStore.changeDetectionState.observerContext);
            this.serviceEditorState.resetExecutionState();
        }
    }
}
export class MultiServicePureExecutionState extends ServicePureExecutionState {
    newKeyParameterModal = false;
    renameKey;
    singleExecutionKey;
    constructor(editorStore, serviceEditorState, execution) {
        super(editorStore, serviceEditorState, execution);
        makeObservable(this, {
            queryState: observable,
            selectedExecutionContextState: observable,
            runtimeEditorState: observable,
            isRunningQuery: observable,
            isGeneratingPlan: observable,
            isOpeningQueryEditor: observable,
            executionResultText: observable,
            executionPlanState: observable,
            newKeyParameterModal: observable,
            renameKey: observable,
            singleExecutionKey: observable,
            showChangeExecModal: observable,
            setExecutionResultText: action,
            closeRuntimeEditor: action,
            openRuntimeEditor: action,
            useCustomRuntime: action,
            setQueryState: action,
            autoSelectRuntimeOnMappingChange: action,
            updateExecutionQuery: action,
            setOpeningQueryEditor: action,
            deleteKeyExecutionParameter: action,
            setNewKeyParameterModal: action,
            changeKeyedExecutionParameter: action,
            setRenameKey: action,
            addExecutionParameter: action,
            setExecutionKey: action,
            changeKeyValue: action,
            setSingleExecutionKey: action,
            setShowChangeExecModal: action,
            setIsRunningQuery: action,
            changeExecution: action,
            generatePlan: flow,
            handleRunQuery: flow,
            runQuery: flow,
        });
        this.execution = execution;
        this.selectedExecutionContextState =
            this.getInitiallySelectedExecutionContextState();
        this.queryState = new ServicePureExecutionQueryState(this.editorStore, execution);
        this.executionPlanState = new ExecutionPlanState(this.editorStore.applicationStore, this.editorStore.graphManagerState);
    }
    get keyedExecutionParameters() {
        return this.execution.executionParameters ?? [];
    }
    setSingleExecutionKey(val) {
        this.singleExecutionKey = val;
    }
    changeExecution() {
        const mappingExecution = this.singleExecutionKey;
        // stub
        const _mapping = mappingExecution?.mapping.value ?? stub_Mapping();
        const mapping = PackageableElementExplicitReference.create(_mapping);
        const runtime = mappingExecution?.runtime ?? stub_PackageableRuntime();
        const _execution = new PureSingleExecution(this.execution.func, this.serviceEditorState.service, mapping, runtime);
        service_setExecution(this.serviceEditorState.service, _execution, this.editorStore.changeDetectionState.observerContext);
        this.serviceEditorState.resetExecutionState();
    }
    setRenameKey(key) {
        this.renameKey = key;
    }
    setNewKeyParameterModal(val) {
        this.newKeyParameterModal = val;
    }
    setExecutionKey(val) {
        pureMultiExecution_setExecutionKey(this.execution, val);
    }
    getInitiallySelectedExecutionContextState() {
        const parameter = this.keyedExecutionParameters[0];
        return parameter
            ? new KeyedExecutionContextState(parameter, this)
            : undefined;
    }
    changeKeyedExecutionParameter(value) {
        this.selectedExecutionContextState = new KeyedExecutionContextState(value, this);
    }
    deleteKeyExecutionParameter(value) {
        pureMultiExecution_deleteExecutionParameter(this.keyedExecutionParameters, value);
        if (value === this.selectedExecutionContextState?.executionContext) {
            this.selectedExecutionContextState =
                this.getInitiallySelectedExecutionContextState();
        }
    }
    addExecutionParameter(value) {
        const _mapping = this.editorStore.graphManagerState.usableMappings[0] ?? stub_Mapping();
        const _key = new KeyedExecutionParameter(value, PackageableElementExplicitReference.create(_mapping), stub_PackageableRuntime());
        pureMultiExecution_addExecutionParameter(this.keyedExecutionParameters, _key, this.editorStore.changeDetectionState.observerContext);
        this.selectedExecutionContextState = new KeyedExecutionContextState(_key, this);
    }
    changeKeyValue(key, value) {
        keyedExecutionParameter_setKey(key, value);
    }
}
//# sourceMappingURL=ServiceExecutionState.js.map