/**
 * 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 { action, flow, observable, makeObservable, computed, flowResult, } from 'mobx';
import { LogEvent, assertErrorThrown, guaranteeNonNullable, guaranteeType, filterByType, ActionState, hashArray, assertTrue, assertNonNullable, } from '@finos/legend-shared';
import { QueryBuilderFilterState } from './filter/QueryBuilderFilterState.js';
import { QueryBuilderFetchStructureState } from './fetch-structure/QueryBuilderFetchStructureState.js';
import { QueryBuilderTextEditorMode, QueryBuilderTextEditorState, } from './QueryBuilderTextEditorState.js';
import { QueryBuilderExplorerState } from './explorer/QueryBuilderExplorerState.js';
import { QueryBuilderResultState } from './QueryBuilderResultState.js';
import { processQueryLambdaFunction, processParameters, } from './QueryBuilderStateBuilder.js';
import { QueryBuilderUnsupportedQueryState } from './QueryBuilderUnsupportedQueryState.js';
import { Accessor, GRAPH_MANAGER_EVENT, CompilationError, extractSourceInformationCoordinates, LambdaFunctionInstanceValue, RawLambda, VariableExpression, observe_ValueSpecification, ObserverContext, isStubbed_RawLambda, buildLambdaVariableExpressions, buildRawLambdaFromLambdaFunction, PrimitiveType, RuntimePointer, QueryExplicitExecutionContext, attachFromQuery, PackageableElementExplicitReference, InMemoryGraphData, } from '@finos/legend-graph';
import { buildLambdaFunction, buildExecutionContextState, } from './QueryBuilderValueSpecificationBuilder.js';
import { QueryFunctionsExplorerState } from './explorer/QueryFunctionsExplorerState.js';
import { QueryBuilderParametersState, } from './QueryBuilderParametersState.js';
import { getQueryBuilderCoreFilterOperators } from './filter/QueryBuilderFilterOperatorLoader.js';
import { QueryBuilderChangeDetectionState } from './QueryBuilderChangeDetectionState.js';
import { QueryBuilderMilestoningState } from './milestoning/QueryBuilderMilestoningState.js';
import { QUERY_BUILDER_STATE_HASH_STRUCTURE } from './QueryBuilderStateHashUtils.js';
import { QUERY_BUILDER_COMMAND_KEY } from './QueryBuilderCommand.js';
import { QueryBuilderWatermarkState } from './watermark/QueryBuilderWatermarkState.js';
import { QueryBuilderConstantsState } from './QueryBuilderConstantsState.js';
import { QueryBuilderCheckEntitlementsState } from './entitlements/QueryBuilderCheckEntitlementsState.js';
import { QueryBuilderTDSState } from './fetch-structure/tds/QueryBuilderTDSState.js';
import { QUERY_BUILDER_PURE_PATH, QUERY_BUILDER_SUPPORTED_GET_ALL_FUNCTIONS, } from '../graph/QueryBuilderMetaModelConst.js';
import { QueryBuilderEmbeddedFromExecutionContextState, QueryBuilderExternalExecutionContextState, } from './QueryBuilderExecutionContextState.js';
import { QUERY_BUILDER_EVENT } from '../__lib__/QueryBuilderEvent.js';
import { QUERY_BUILDER_SETTING_KEY } from '../__lib__/QueryBuilderSetting.js';
import { QueryBuilderChangeHistoryState } from './QueryBuilderChangeHistoryState.js';
import {} from './query-workflow/QueryBuilderWorkFlowState.js';
import {} from './QueryChatState.js';
import { createDataCubeViewerStateFromQueryBuilder } from './data-cube/QueryBuilderDataCubeHelper.js';
import { QueryBuilderTelemetryHelper } from '../__lib__/QueryBuilderTelemetryHelper.js';
export var QUERY_BUILDER_LAMBDA_WRITER_MODE;
(function (QUERY_BUILDER_LAMBDA_WRITER_MODE) {
    QUERY_BUILDER_LAMBDA_WRITER_MODE["STANDARD"] = "STANDARD";
    QUERY_BUILDER_LAMBDA_WRITER_MODE["TYPED_FETCH_STRUCTURE"] = "TYPED_FETCH_STRUCTURE";
})(QUERY_BUILDER_LAMBDA_WRITER_MODE || (QUERY_BUILDER_LAMBDA_WRITER_MODE = {}));
export class ExtraOptionsConfig {
    label;
    type;
    options;
    selectedValue;
    onChange;
    placeholder;
    disabled;
    constructor(label, type, options, selectedValue, onChange, placeholder, disabled) {
        this.label = label;
        this.type = type;
        this.options = options;
        this.selectedValue = selectedValue;
        this.onChange = onChange;
        this.placeholder = placeholder;
        this.disabled = disabled;
        makeObservable(this, {
            options: observable,
            setOptions: action,
        });
    }
    setOptions(options) {
        this.options = options;
    }
}
export class QueryBuilderState {
    applicationStore;
    graphManagerState;
    changeDetectionState;
    queryCompileState = ActionState.create();
    observerContext;
    config;
    workflowState;
    explorerState;
    functionsExplorerState;
    parametersState;
    constantState;
    milestoningState;
    fetchStructureState;
    filterState;
    watermarkState;
    checkEntitlementsState;
    filterOperators = getQueryBuilderCoreFilterOperators();
    resultState;
    textEditorState;
    unsupportedQueryState;
    changeHistoryState;
    isQueryChatOpened;
    showFunctionsExplorerPanel = false;
    showParametersPanel = false;
    isEditingWatermark = false;
    isCheckingEntitlments = false;
    isCalendarEnabled = false;
    isLocalModeEnabled = false;
    dataCubeViewerState;
    INTERNAL__enableInitializingDefaultSimpleExpressionValue = false;
    lambdaWriteMode = QUERY_BUILDER_LAMBDA_WRITER_MODE.STANDARD;
    sourceElement;
    getAllFunction = QUERY_BUILDER_SUPPORTED_GET_ALL_FUNCTIONS.GET_ALL;
    executionContextState;
    internalizeState;
    queryChatState;
    // NOTE: This property contains information about workflow used
    // to create this state. This should only be used to add additional
    // information to query builder analytics.
    sourceInfo;
    // NOTE: this makes it so that we need to import components in stores code,
    // we probably want to refactor to an extension mechanism
    TEMPORARY__setupPanelContentRenderer;
    constructor(applicationStore, graphManagerState, workflowState, config, sourceInfo) {
        makeObservable(this, {
            explorerState: observable,
            parametersState: observable,
            constantState: observable,
            functionsExplorerState: observable,
            fetchStructureState: observable,
            filterState: observable,
            watermarkState: observable,
            milestoningState: observable,
            checkEntitlementsState: observable,
            resultState: observable,
            textEditorState: observable,
            unsupportedQueryState: observable,
            showFunctionsExplorerPanel: observable,
            showParametersPanel: observable,
            isEditingWatermark: observable,
            isCheckingEntitlments: observable,
            isCalendarEnabled: observable,
            changeDetectionState: observable,
            changeHistoryState: observable,
            executionContextState: observable,
            sourceElement: observable,
            queryChatState: observable,
            isQueryChatOpened: observable,
            isLocalModeEnabled: observable,
            dataCubeViewerState: observable,
            getAllFunction: observable,
            lambdaWriteMode: observable,
            INTERNAL__enableInitializingDefaultSimpleExpressionValue: observable,
            sideBarClassName: computed,
            sourceClass: computed,
            sourceAccessor: computed,
            sourceRelationType: computed,
            isQuerySupported: computed,
            allValidationIssues: computed,
            canBuildQuery: computed,
            useRelation: computed,
            setShowFunctionsExplorerPanel: action,
            setShowParametersPanel: action,
            setIsEditingWatermark: action,
            setIsCalendarEnabled: action,
            setDataCubeViewerState: action,
            openDataCubeEngine: action,
            setIsCheckingEntitlments: action,
            setSourceElement: action,
            setIsQueryChatOpened: action,
            setIsLocalModeEnabled: action,
            setGetAllFunction: action,
            setLambdaWriteMode: action,
            setINTERNAL__enableInitializingDefaultSimpleExpressionValue: action,
            TEMPORARY_initializeExecContext: action,
            resetQueryResult: action,
            resetQueryContent: action,
            changeSourceElement: action,
            changeMapping: action,
            changeRuntime: action,
            setExecutionContextState: action,
            setQueryChatState: action,
            rebuildWithQuery: action,
            compileQuery: flow,
            hashCode: computed,
        });
        this.applicationStore = applicationStore;
        this.graphManagerState = graphManagerState;
        this.executionContextState = this.TEMPORARY_initializeExecContext(Boolean(config?.enableTypedTDS));
        this.milestoningState = new QueryBuilderMilestoningState(this);
        this.explorerState = new QueryBuilderExplorerState(this);
        this.parametersState = new QueryBuilderParametersState(this);
        this.constantState = new QueryBuilderConstantsState(this);
        this.functionsExplorerState = new QueryFunctionsExplorerState(this);
        this.fetchStructureState = new QueryBuilderFetchStructureState(this);
        this.filterState = new QueryBuilderFilterState(this, this.filterOperators);
        this.watermarkState = new QueryBuilderWatermarkState(this);
        this.checkEntitlementsState = new QueryBuilderCheckEntitlementsState(this);
        this.resultState = new QueryBuilderResultState(this);
        this.textEditorState = new QueryBuilderTextEditorState(this);
        this.unsupportedQueryState = new QueryBuilderUnsupportedQueryState(this);
        this.observerContext = new ObserverContext(this.graphManagerState.pluginManager.getPureGraphManagerPlugins());
        this.changeDetectionState = new QueryBuilderChangeDetectionState(this);
        this.changeHistoryState = new QueryBuilderChangeHistoryState(this);
        this.config = config;
        this.workflowState = workflowState;
        this.sourceInfo = sourceInfo;
        this.isQueryChatOpened =
            (!this.config?.TEMPORARY__disableQueryBuilderChat &&
                this.applicationStore.settingService.getBooleanValue(QUERY_BUILDER_SETTING_KEY.SHOW_QUERY_CHAT_PANEL)) ??
                false;
    }
    TEMPORARY_initializeExecContext(isTypedTDS) {
        if (isTypedTDS) {
            const context = new QueryBuilderEmbeddedFromExecutionContextState(this);
            this.setLambdaWriteMode(QUERY_BUILDER_LAMBDA_WRITER_MODE.TYPED_FETCH_STRUCTURE);
            return context;
        }
        return new QueryBuilderExternalExecutionContextState(this);
    }
    get useRelation() {
        return this.sourceElement instanceof Accessor || this.isFetchStructureTyped;
    }
    get isMappingReadOnly() {
        return false;
    }
    get isRuntimeReadOnly() {
        return false;
    }
    get sideBarClassName() {
        return undefined;
    }
    get isParameterSupportDisabled() {
        return false;
    }
    get isResultPanelHidden() {
        return false;
    }
    get floatingExecutionElements() {
        return undefined;
    }
    /**
     * This flag is for turning on/off DnD support from projection panel to filter panel,
     * and will be leveraged when the concepts of workflows are introduced into query builder.
     */
    get TEMPORARY__isDnDFetchStructureToFilterSupported() {
        return true;
    }
    get allVariables() {
        const parameterVars = this.parametersState.parameterStates.map((paramState) => paramState.parameter);
        const letVars = this.constantState.constants.map((letVar) => letVar.variable);
        return [...parameterVars, ...letVars];
    }
    get allVariableNames() {
        return this.allVariables.map((e) => e.name);
    }
    get isFetchStructureTyped() {
        return (this.lambdaWriteMode ===
            QUERY_BUILDER_LAMBDA_WRITER_MODE.TYPED_FETCH_STRUCTURE);
    }
    get forceFromExpressionForExec() {
        return this.isFetchStructureTyped;
    }
    get requiresMappingForExecution() {
        return true;
    }
    setLambdaWriteMode(val) {
        this.lambdaWriteMode = val;
    }
    getQueryExecutionContext() {
        const queryExeContext = new QueryExplicitExecutionContext();
        const runtimeValue = guaranteeType(this.executionContextState.runtimeValue, RuntimePointer, 'Query runtime must be of type runtime pointer');
        assertNonNullable(this.executionContextState.mapping, 'Query required mapping to update');
        queryExeContext.mapping = PackageableElementExplicitReference.create(this.executionContextState.mapping);
        queryExeContext.runtime = runtimeValue.packageableRuntime;
        return queryExeContext;
    }
    async propagateExecutionContextChange(isGraphBuildingNotRequired) {
        const propagateFuncHelpers = this.applicationStore.pluginManager
            .getApplicationPlugins()
            .flatMap((plugin) => plugin.getExtraQueryBuilderPropagateExecutionContextChangeHelper?.() ?? []);
        for (const helper of propagateFuncHelpers) {
            const propagateFuncHelper = helper(this, isGraphBuildingNotRequired);
            if (propagateFuncHelper) {
                await propagateFuncHelper();
                return;
            }
        }
    }
    /**
     * Gets information about the current queryBuilderState.
     * This information can be used as a part of analytics
     */
    getStateInfo() {
        if (this.sourceInfo) {
            const classPath = this.sourceClass?.path;
            const mappingPath = this.executionContextState.mapping?.path;
            const runtimePath = this.executionContextState.runtimeValue instanceof RuntimePointer
                ? this.executionContextState.runtimeValue.packageableRuntime.value
                    .path
                : undefined;
            if (classPath && mappingPath && runtimePath) {
                const contextInfo = {
                    class: classPath,
                    mapping: mappingPath,
                    runtime: runtimePath,
                };
                return Object.assign({}, this.sourceInfo, contextInfo);
            }
        }
        return undefined;
    }
    setIsQueryChatOpened(val) {
        this.isQueryChatOpened = val;
        this.applicationStore.settingService.persistValue(QUERY_BUILDER_SETTING_KEY.SHOW_QUERY_CHAT_PANEL, val);
    }
    setIsLocalModeEnabled(val) {
        this.isLocalModeEnabled = val;
    }
    setDataCubeViewerState(val) {
        this.dataCubeViewerState = val;
    }
    setInternalize(val) {
        this.internalizeState = val;
    }
    setQueryChatState(val) {
        this.queryChatState = val;
    }
    setShowFunctionsExplorerPanel(val) {
        this.showFunctionsExplorerPanel = val;
    }
    setShowParametersPanel(val) {
        this.showParametersPanel = val;
    }
    setIsEditingWatermark(val) {
        this.isEditingWatermark = val;
    }
    setIsCheckingEntitlments(val) {
        this.isCheckingEntitlments = val;
    }
    setIsCalendarEnabled(val) {
        this.isCalendarEnabled = val;
    }
    /**
     * Convenience getter that returns the class only when the source
     * type is a Class (not a RelationType). Use this in code paths
     * that are Class-specific (milestoning, explorer tree, graph-fetch, etc.).
     */
    get sourceClass() {
        return this.sourceElement instanceof Accessor
            ? undefined
            : this.sourceElement;
    }
    get sourceAccessor() {
        return this.sourceElement instanceof Accessor
            ? this.sourceElement
            : undefined;
    }
    get sourceRelationType() {
        return this.sourceAccessor?.relationType;
    }
    setSourceElement(val) {
        this.sourceElement = val;
    }
    setExecutionContextState(val) {
        this.executionContextState = val;
    }
    setGetAllFunction(val) {
        this.getAllFunction = val;
    }
    setINTERNAL__enableInitializingDefaultSimpleExpressionValue(val) {
        this.INTERNAL__enableInitializingDefaultSimpleExpressionValue = val;
    }
    get isQuerySupported() {
        return !this.unsupportedQueryState.rawLambda;
    }
    async openDataCubeEngine() {
        try {
            QueryBuilderTelemetryHelper.logEvent_EmbeddedDataCubeLaunched(this.applicationStore.telemetryService);
            this.setDataCubeViewerState(await createDataCubeViewerStateFromQueryBuilder(this));
        }
        catch (error) {
            assertErrorThrown(error);
            this.applicationStore.notificationService.notifyError(`Unable to open data cube in query builder`);
        }
    }
    registerCommands() {
        this.applicationStore.commandService.registerCommand({
            key: QUERY_BUILDER_COMMAND_KEY.COMPILE,
            action: () => {
                flowResult(this.compileQuery()).catch(this.applicationStore.alertUnhandledError);
            },
        });
    }
    // Used to determine if variable is used within query
    // For places where we don't know, we will assume the variable is not used (i.e projection derivation column)
    isVariableUsed(variable, options) {
        const isVariableUsedInBody = this.filterState.isVariableUsed(variable) ||
            this.watermarkState.isVariableUsed(variable) ||
            this.fetchStructureState.implementation.isVariableUsed(variable);
        return options?.exculdeMilestoningState
            ? isVariableUsedInBody
            : this.milestoningState.isVariableUsed(variable) || isVariableUsedInBody;
    }
    deregisterCommands() {
        [QUERY_BUILDER_COMMAND_KEY.COMPILE].forEach((key) => this.applicationStore.commandService.deregisterCommand(key));
    }
    resetQueryResult(options) {
        const resultState = new QueryBuilderResultState(this);
        resultState.setPreviewLimit(this.resultState.previewLimit);
        if (options?.preserveResult) {
            resultState.setExecutionResult(this.resultState.executionResult);
            resultState.setExecutionDuration(this.resultState.executionDuration);
            resultState.latestRunHashCode = this.resultState.latestRunHashCode;
        }
        if (options?.gridConfig) {
            this.isLocalModeEnabled = true;
            resultState.handlePreConfiguredGridConfig(options.gridConfig);
        }
        this.resultState = resultState;
    }
    resetQueryContent() {
        this.textEditorState = new QueryBuilderTextEditorState(this);
        this.unsupportedQueryState = new QueryBuilderUnsupportedQueryState(this);
        this.milestoningState = new QueryBuilderMilestoningState(this);
        const mappingModelCoverageAnalysisResult = this.explorerState.mappingModelCoverageAnalysisResult;
        this.explorerState = new QueryBuilderExplorerState(this);
        if (mappingModelCoverageAnalysisResult) {
            this.explorerState.mappingModelCoverageAnalysisResult =
                mappingModelCoverageAnalysisResult;
        }
        this.explorerState.refreshTreeData();
        this.constantState = new QueryBuilderConstantsState(this);
        this.functionsExplorerState = new QueryFunctionsExplorerState(this);
        this.parametersState = new QueryBuilderParametersState(this);
        this.filterState = new QueryBuilderFilterState(this, this.filterOperators);
        this.watermarkState = new QueryBuilderWatermarkState(this);
        this.checkEntitlementsState = new QueryBuilderCheckEntitlementsState(this);
        this.isCalendarEnabled = false;
        const currentFetchStructureImplementationType = this.fetchStructureState.implementation.type;
        this.fetchStructureState = new QueryBuilderFetchStructureState(this);
        if (currentFetchStructureImplementationType !==
            this.fetchStructureState.implementation.type) {
            this.fetchStructureState.changeImplementation(currentFetchStructureImplementationType);
        }
    }
    changeSourceElement(val) {
        this.resetQueryResult();
        this.resetQueryContent();
        this.setGetAllFunction(QUERY_BUILDER_SUPPORTED_GET_ALL_FUNCTIONS.GET_ALL);
        this.setSourceElement(val);
        this.explorerState.refreshTreeData();
        this.fetchStructureState.implementation.onClassChange();
        this.milestoningState.updateMilestoningConfiguration();
        this.changeHistoryState.cacheNewQuery(this.buildQuery());
    }
    changeMapping(val, options) {
        this.resetQueryResult();
        if (!options?.keepQueryContent) {
            this.resetQueryContent();
            this.setGetAllFunction(QUERY_BUILDER_SUPPORTED_GET_ALL_FUNCTIONS.GET_ALL);
            this.milestoningState.updateMilestoningConfiguration();
        }
        this.executionContextState.setMapping(val);
    }
    changeRuntime(val) {
        this.resetQueryResult();
        this.executionContextState.setRuntimeValue(val);
    }
    getCurrentParameterValues() {
        if (this.parametersState.parameterStates.length) {
            const result = new Map();
            this.parametersState.parameterStates.forEach((paramState) => {
                const val = paramState.value;
                if (val) {
                    result.set(paramState.variableName, val);
                }
            });
            return result;
        }
        return undefined;
    }
    getGridConfig() {
        // for now we will only save in local mode
        if (this.isLocalModeEnabled && this.resultState.gridConfig) {
            return this.resultState.getQueryGridConfig();
        }
        return undefined;
    }
    buildQuery(options) {
        if (!this.isQuerySupported) {
            const parameters = this.parametersState.parameterStates.map((e) => this.graphManagerState.graphManager.serializeValueSpecification(e.parameter));
            this.unsupportedQueryState.setRawLambda(new RawLambda(parameters, this.unsupportedQueryState.rawLambda?.body));
            return guaranteeNonNullable(this.unsupportedQueryState.rawLambda);
        }
        return buildRawLambdaFromLambdaFunction(buildLambdaFunction(this, {
            keepSourceInformation: Boolean(options?.keepSourceInformation),
            useTypedRelationFunctions: this.isFetchStructureTyped,
        }), this.graphManagerState);
    }
    /**
     * Builds the raw lambda intended for persistence (saving to query store).
     * The default implementation delegates to buildQuery(). Subclasses that embed
     * execution context inside the lambda body (e.g. DataProductQueryBuilderState)
     * should override this to return a plain lambda without that wrapping, since
     * the execution context is persisted separately via query.executionContext.
     */
    buildQueryForPersistence() {
        return this.buildQuery();
    }
    buildFromQuery() {
        assertTrue(this.isQuerySupported, 'Query must be supported to build from function');
        const mapping = guaranteeNonNullable(this.executionContextState.mapping, 'Mapping required to build from() function');
        const runtime = guaranteeNonNullable(this.executionContextState.runtimeValue, 'Runtime required to build from query');
        const runtimePointer = guaranteeType(runtime, RuntimePointer).packageableRuntime;
        const lambdaFunc = buildLambdaFunction(this);
        const fromQuery = attachFromQuery(lambdaFunc, mapping, runtimePointer.value);
        return buildRawLambdaFromLambdaFunction(fromQuery, this.graphManagerState);
    }
    /**
     * Builds the execution context expression (e.g. from()) for the lambda function.
     * Subclasses can override this to customize the execution context building.
     */
    buildExecutionContextExpression(lambdaFunction) {
        return buildExecutionContextState(this.executionContextState, lambdaFunction);
    }
    getQueryReturnType() {
        if (this.fetchStructureState.implementation instanceof QueryBuilderTDSState) {
            return this.useRelation
                ? this.graphManagerState.graph.getType(QUERY_BUILDER_PURE_PATH.RELATION)
                : this.graphManagerState.graph.getClass(QUERY_BUILDER_PURE_PATH.TDS_TABULAR_DATASET);
        }
        return PrimitiveType.STRING;
    }
    initializeWithQuery(query, defaultParameterValues, gridConfig) {
        this.rebuildWithQuery(query, {
            defaultParameterValues,
        });
        this.resetQueryResult({ gridConfig });
        this.changeDetectionState.initialize(query);
        this.changeHistoryState.initialize(query);
    }
    /**
     * Process the provided query, and rebuild the query builder state.
     */
    rebuildWithQuery(query, options) {
        let previousStateParameterValues = undefined;
        try {
            const paramValues = new Map();
            if (options?.preserveParameterValues) {
                this.parametersState.parameterStates.forEach((ps) => {
                    paramValues.set(ps.parameter.name, {
                        variable: ps.parameter,
                        value: ps.value,
                    });
                });
                previousStateParameterValues = paramValues;
            }
            else if (options?.defaultParameterValues?.size) {
                Array.from(options.defaultParameterValues.entries()).forEach(([k, v]) => {
                    paramValues.set(k, {
                        variable: k,
                        value: v,
                    });
                });
                previousStateParameterValues = paramValues;
            }
            this.resetQueryResult({ preserveResult: options?.preserveResult });
            this.resetQueryContent();
            if (!isStubbed_RawLambda(query)) {
                const valueSpec = observe_ValueSpecification(this.graphManagerState.graphManager.buildValueSpecification(this.graphManagerState.graphManager.serializeRawValueSpecification(query), this.graphManagerState.graph), this.observerContext);
                const compiledValueSpecification = guaranteeType(valueSpec, LambdaFunctionInstanceValue, `Can't build query state: query builder only support lambda`);
                processQueryLambdaFunction(guaranteeNonNullable(compiledValueSpecification.values[0]), this, {
                    parameterValues: previousStateParameterValues,
                });
            }
            if (this.parametersState.parameterStates.filter((paramState) => !this.milestoningState.isMilestoningParameter(paramState.parameter)).length > 0) {
                this.setShowParametersPanel(true);
            }
            this.fetchStructureState.initializeWithQuery();
        }
        catch (error) {
            assertErrorThrown(error);
            this.applicationStore.logService.error(LogEvent.create(QUERY_BUILDER_EVENT.UNSUPPORTED_QUERY_LAUNCH), error);
            this.resetQueryResult({ preserveResult: options?.preserveResult });
            this.resetQueryContent();
            this.unsupportedQueryState.setLambdaError(error);
            this.unsupportedQueryState.setRawLambda(query);
            this.setSourceElement(undefined);
            const parameters = buildLambdaVariableExpressions(query, this.graphManagerState)
                .map((param) => observe_ValueSpecification(param, this.observerContext))
                .filter(filterByType(VariableExpression));
            processParameters(parameters, this, {
                parameterValues: previousStateParameterValues,
            });
        }
    }
    *compileQuery() {
        if (!this.textEditorState.mode) {
            this.queryCompileState.inProgress();
            this.fetchStructureState.implementation.clearCompilationError();
            // form mode
            try {
                this.textEditorState.setCompilationError(undefined);
                // NOTE: retain the source information on the lambda in order to be able
                // to pin-point compilation issue in form mode
                (yield this.graphManagerState.graphManager.getLambdaReturnType(this.buildQuery({ keepSourceInformation: true }), this.graphManagerState.graph, { keepSourceInformation: true }));
                this.applicationStore.notificationService.notifySuccess('Compiled successfully');
            }
            catch (error) {
                assertErrorThrown(error);
                this.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.COMPILATION_FAILURE), error);
                let fallbackToTextModeForDebugging = true;
                // if compilation failed, we try to reveal the error in form mode,
                // if even this fail, we will fall back to show it in text mode
                if (error instanceof CompilationError && error.sourceInformation) {
                    fallbackToTextModeForDebugging =
                        !this.fetchStructureState.implementation.revealCompilationError(error);
                }
                // decide if we need to fall back to text mode for debugging
                if (fallbackToTextModeForDebugging) {
                    this.applicationStore.notificationService.notifyWarning('Compilation failed and error cannot be located in form mode. Redirected to text mode for debugging.');
                    this.textEditorState.openModal(QueryBuilderTextEditorMode.TEXT);
                    // TODO: trigger another compilation to pin-point the issue
                    // since we're using the lambda editor right now, we are a little bit limitted
                    // in terms of the timing to do compilation (since we're using an `useEffect` to
                    // convert the lambda to grammar text), we might as well wait for the refactor
                    // of query builder text-mode
                    // See https://github.com/finos/legend-studio/issues/319
                }
                else {
                    this.applicationStore.notificationService.notifyWarning(`Compilation failed: ${error.message}`);
                }
            }
            finally {
                this.queryCompileState.complete();
            }
        }
        else if (this.textEditorState.mode === QueryBuilderTextEditorMode.TEXT) {
            this.queryCompileState.inProgress();
            try {
                this.textEditorState.setCompilationError(undefined);
                (yield this.graphManagerState.graphManager.getLambdaReturnType(this.textEditorState.rawLambdaState.lambda, this.graphManagerState.graph, { keepSourceInformation: true }));
                this.applicationStore.notificationService.notifySuccess('Compiled successfully');
            }
            catch (error) {
                assertErrorThrown(error);
                if (error instanceof CompilationError) {
                    this.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.COMPILATION_FAILURE), error);
                    this.applicationStore.notificationService.notifyWarning(`Compilation failed: ${error.message}`, error.trace);
                    const errorElementCoordinates = extractSourceInformationCoordinates(error.sourceInformation);
                    if (errorElementCoordinates) {
                        this.textEditorState.setCompilationError(error);
                    }
                }
            }
            finally {
                this.queryCompileState.complete();
            }
        }
    }
    get allValidationIssues() {
        return this.fetchStructureState.implementation.allValidationIssues.concat(this.filterState.allValidationIssues);
    }
    get canBuildQuery() {
        return (!this.filterState.hasInvalidFilterValues &&
            !this.filterState.hasInvalidDerivedPropertyParameters &&
            !this.fetchStructureState.implementation.hasInvalidFilterValues &&
            !this.fetchStructureState.implementation
                .hasInvalidDerivedPropertyParameters);
    }
    buildFunctionAnalysisInfo() {
        return undefined;
    }
    getGraphData() {
        return new InMemoryGraphData(this.graphManagerState.graph);
    }
    /**
     * This method can be used to simplify the current query builder state
     * to a basic one that can be used for testing or some special operations,
     * see {@link INTERNAL__BasicQueryBuilderState} for more details
     */
    INTERNAL__toBasicQueryBuilderState() {
        // eslint-disable-next-line @typescript-eslint/no-use-before-define
        const basicState = new INTERNAL__BasicQueryBuilderState(this.applicationStore, this.graphManagerState, this.workflowState, undefined);
        basicState.sourceElement = this.sourceElement;
        basicState.executionContextState.mapping =
            this.executionContextState.mapping;
        basicState.executionContextState.runtimeValue =
            this.executionContextState.runtimeValue;
        return basicState;
    }
    get hashCode() {
        return hashArray([
            QUERY_BUILDER_STATE_HASH_STRUCTURE.QUERY_BUILDER_STATE,
            this.unsupportedQueryState,
            this.milestoningState,
            this.parametersState,
            this.filterState,
            this.watermarkState,
            this.checkEntitlementsState,
            this.fetchStructureState.implementation,
        ]);
    }
}
/**
 * Base query builder state with result panel hidden.
 * This is useful for scenarios where the query builder is used
 * only for query construction without execution/result display.
 */
export class BaseQueryBuilderState extends QueryBuilderState {
    get isResultPanelHidden() {
        return true;
    }
}
/**
 * This type is used for testing and analytics operation in query builder.
 * For example, we use this to build the preview data lambda, or to build the auto-complete lambda
 * in filters.
 *
 * NOTE: The latter is quite clever since query-builder itself is used to build the lambda (i.e. dogfooding),
 * unfortunately, it creates a circular dependency between QueryBuilderState and PreviewData/AutoComplete
 *
 * @internal
 */
export class INTERNAL__BasicQueryBuilderState extends QueryBuilderState {
}
//# sourceMappingURL=QueryBuilderState.js.map