/**
 * 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, computed, flow, flowResult, makeObservable, observable, } from 'mobx';
import { GRAPH_EDITOR_MODE } from './EditorConfig.js';
import { LogEvent, UnsupportedOperationError, assertErrorThrown, assertTrue, isNonNullable, NetworkClientError, guaranteeNonNullable, StopWatch, filterByType, ActionState, } from '@finos/legend-shared';
import { ElementEditorState } from './editor-state/element-editor-state/ElementEditorState.js';
import { GraphGenerationState } from './editor-state/GraphGenerationState.js';
import { MODEL_IMPORT_NATIVE_INPUT_TYPE } from './editor-state/ModelImporterState.js';
import { EntitiesWithOrigin } from '@finos/legend-storage';
import { ProjectConfiguration, applyEntityChanges, } from '@finos/legend-server-sdlc';
import { ProjectVersionEntities, ProjectDependencyCoordinates, RawProjectDependencyReport, buildDependencyReport, } from '@finos/legend-server-depot';
import { GRAPH_MANAGER_EVENT, Package, Profile, PrimitiveType, Enumeration, Class, Association, Mapping, ConcreteFunctionDefinition, Service, FlatData, PackageableConnection, PackageableRuntime, FileGenerationSpecification, GenerationSpecification, Measure, Unit, Database, SectionIndex, DependencyGraphBuilderError, GraphDataDeserializationError, DataElement, createGraphBuilderReport, ExecutionEnvironmentInstance, SnowflakeApp, SnowflakeM2MUdf, GraphEntities, HostedService, DataProduct, IngestDefinition, MemSQLFunction, } from '@finos/legend-graph';
import { CONFIGURATION_EDITOR_TAB } from './editor-state/project-configuration-editor-state/ProjectConfigurationEditorState.js';
import { PACKAGEABLE_ELEMENT_TYPE } from './utils/ModelClassifierUtils.js';
import { LEGEND_STUDIO_APP_EVENT } from '../../__lib__/LegendStudioEvent.js';
import { LEGEND_STUDIO_SETTING_KEY } from '../../__lib__/LegendStudioSetting.js';
import { LegendStudioTelemetryHelper } from '../../__lib__/LegendStudioTelemetryHelper.js';
export var GraphBuilderStatus;
(function (GraphBuilderStatus) {
    GraphBuilderStatus["SUCCEEDED"] = "SUCCEEDED";
    GraphBuilderStatus["FAILED"] = "FAILED";
    GraphBuilderStatus["REDIRECTED_TO_TEXT_MODE"] = "REDIRECTED_TO_TEXT_MODE";
})(GraphBuilderStatus || (GraphBuilderStatus = {}));
export var GraphCompilationOutcome;
(function (GraphCompilationOutcome) {
    GraphCompilationOutcome["SKIPPED"] = "SKIPPED";
    GraphCompilationOutcome["SUCCEEDED"] = "SUCCEEDED";
    GraphCompilationOutcome["FAILED"] = "FAILED";
})(GraphCompilationOutcome || (GraphCompilationOutcome = {}));
export class EditorGraphState {
    editorStore;
    graphGenerationState;
    isInitializingGraph = false;
    isRunningGlobalCompile = false;
    isRunningGlobalGenerate = false;
    isApplicationLeavingGraphEditMode = false;
    isUpdatingGraph = false; // critical synchronous update to refresh the graph
    isUpdatingApplication = false; // including graph update and async operations such as change detection
    functionActivatorConfigurations = [];
    relationalDatabseTypeConfigurations;
    warnings = [];
    error;
    compilationResultEntities = [];
    enableStrictMode;
    mostRecentCompilationGraphHash = undefined;
    mostRecentCompilationOutcome = undefined;
    constructor(editorStore) {
        makeObservable(this, {
            isInitializingGraph: observable,
            isRunningGlobalCompile: observable,
            isRunningGlobalGenerate: observable,
            isApplicationLeavingGraphEditMode: observable,
            isUpdatingGraph: observable,
            isUpdatingApplication: observable,
            functionActivatorConfigurations: observable,
            mostRecentCompilationGraphHash: observable,
            mostRecentCompilationOutcome: observable,
            warnings: observable,
            error: observable,
            enableStrictMode: observable,
            relationalDatabseTypeConfigurations: observable,
            problems: computed,
            areProblemsStale: computed,
            isApplicationUpdateOperationIsRunning: computed,
            clearProblems: action,
            setEnableStrictMode: action,
            setMostRecentCompilationGraphHash: action,
            fetchAvailableRelationalDatabseTypeConfigurations: flow,
            fetchAvailableFunctionActivatorConfigurations: flow,
            buildGraph: flow,
            loadEntityChangesToGraph: flow,
            updateGenerationGraphAndApplication: flow,
            rebuildDependencies: flow,
            buildGraphForLazyText: flow,
        });
        this.editorStore = editorStore;
        this.graphGenerationState = new GraphGenerationState(this.editorStore);
        this.enableStrictMode =
            this.editorStore.applicationStore.settingService.getBooleanValue(LEGEND_STUDIO_SETTING_KEY.EDITOR_STRICT_MODE) ?? false;
    }
    get problems() {
        return [this.error, ...this.warnings].filter(isNonNullable);
    }
    /**
     * This function is temporary. There is no good way to detect if a problem not coming from
     * the main graph at the moment. In text mode, we can rely on the fact that the source information
     * has line 0 column 0. But this is not the case for form mode, so this is just temporary
     * to help with text-mode.
     */
    TEMPORARY__removeDependencyProblems(problems) {
        return problems.filter((problem) => {
            if (problem.sourceInformation) {
                return !(problem.sourceInformation.startLine === 0 &&
                    problem.sourceInformation.startColumn === 0 &&
                    problem.sourceInformation.endLine === 0 &&
                    problem.sourceInformation.endColumn === 0);
            }
            return true;
        });
    }
    setMostRecentCompilationGraphHash(val) {
        this.mostRecentCompilationGraphHash = val;
    }
    setMostRecentCompilationOutcome(val) {
        this.mostRecentCompilationOutcome = val;
    }
    get areProblemsStale() {
        return (this.mostRecentCompilationGraphHash !==
            this.editorStore.graphEditorMode.getCurrentGraphHash());
    }
    get isApplicationUpdateOperationIsRunning() {
        return (this.isRunningGlobalCompile ||
            this.isRunningGlobalGenerate ||
            this.isApplicationLeavingGraphEditMode ||
            this.isUpdatingApplication ||
            this.isInitializingGraph);
    }
    checkIfApplicationUpdateOperationIsRunning() {
        if (this.isRunningGlobalGenerate) {
            this.editorStore.applicationStore.notificationService.notifyWarning('Please wait for model generation to complete');
            return true;
        }
        if (this.isRunningGlobalCompile) {
            this.editorStore.applicationStore.notificationService.notifyWarning('Please wait for graph compilation to complete');
            return true;
        }
        if (this.isApplicationLeavingGraphEditMode) {
            this.editorStore.applicationStore.notificationService.notifyWarning('Please wait for editor to leave edit mode completely');
            return true;
        }
        if (this.isUpdatingApplication) {
            this.editorStore.applicationStore.notificationService.notifyWarning('Please wait for editor state to rebuild');
            return true;
        }
        if (this.isInitializingGraph) {
            this.editorStore.applicationStore.notificationService.notifyWarning('Please wait for editor initialization to complete');
            return true;
        }
        return false;
    }
    clearProblems() {
        this.error = undefined;
        this.editorStore.tabManagerState.tabs
            .filter(filterByType(ElementEditorState))
            .forEach((editorState) => editorState.clearCompilationError());
        this.mostRecentCompilationGraphHash = undefined;
        this.warnings = [];
    }
    setEnableStrictMode(val) {
        this.enableStrictMode = val;
    }
    *fetchAvailableFunctionActivatorConfigurations() {
        try {
            this.functionActivatorConfigurations =
                (yield this.editorStore.graphManagerState.graphManager.getAvailableFunctionActivatorConfigurations(this.editorStore.graphManagerState.coreModel, this.editorStore.graphManagerState.systemModel));
        }
        catch (error) {
            assertErrorThrown(error);
            this.editorStore.applicationStore.logService.error(LogEvent.create(LEGEND_STUDIO_APP_EVENT.GENERIC_FAILURE), error);
            this.editorStore.applicationStore.notificationService.notifyError(error);
        }
    }
    *fetchAvailableRelationalDatabseTypeConfigurations() {
        try {
            this.relationalDatabseTypeConfigurations =
                (yield this.editorStore.graphManagerState.graphManager.getAvailableRelationalDatabaseTypeConfigurations());
        }
        catch (error) {
            assertErrorThrown(error);
            this.editorStore.applicationStore.logService.error(LogEvent.create(LEGEND_STUDIO_APP_EVENT.GENERIC_FAILURE), error);
            this.editorStore.applicationStore.notificationService.notifyError(error);
        }
    }
    findRelationalDatabaseTypeConfiguration(type) {
        return this.relationalDatabseTypeConfigurations?.find((aFlow) => aFlow.type === type);
    }
    *buildGraph(entities) {
        try {
            this.isInitializingGraph = true;
            const stopWatch = new StopWatch();
            // reset
            this.editorStore.graphManagerState.resetGraph();
            // fetch and build dependencies
            stopWatch.record();
            const dependencyManager = this.editorStore.graphManagerState.graphManager.createDependencyManager();
            this.editorStore.graphManagerState.graph.dependencyManager =
                dependencyManager;
            this.editorStore.graphManagerState.dependenciesBuildState.setMessage(`Fetching dependencies...`);
            const dependencyEntitiesIndex = (yield flowResult(this.getIndexedDependencyEntities()));
            stopWatch.record(GRAPH_MANAGER_EVENT.FETCH_GRAPH_DEPENDENCIES__SUCCESS);
            const dependency_buildReport = createGraphBuilderReport();
            yield this.editorStore.graphManagerState.graphManager.buildDependencies(this.editorStore.graphManagerState.coreModel, this.editorStore.graphManagerState.systemModel, dependencyManager, dependencyEntitiesIndex, this.editorStore.graphManagerState.dependenciesBuildState, {}, dependency_buildReport);
            dependency_buildReport.timings[GRAPH_MANAGER_EVENT.FETCH_GRAPH_DEPENDENCIES__SUCCESS] = stopWatch.getRecord(GRAPH_MANAGER_EVENT.FETCH_GRAPH_DEPENDENCIES__SUCCESS);
            // build graph
            const graph_buildReport = createGraphBuilderReport();
            yield this.editorStore.graphManagerState.graphManager.buildGraph(this.editorStore.graphManagerState.graph, entities, this.editorStore.graphManagerState.graphBuildState, {
                TEMPORARY__preserveSectionIndex: this.editorStore.applicationStore.config.options
                    .TEMPORARY__preserveSectionIndex,
                strict: this.enableStrictMode,
            }, graph_buildReport);
            // build generations
            const generation_buildReport = createGraphBuilderReport();
            yield this.editorStore.graphManagerState.graphManager.buildGenerations(this.editorStore.graphManagerState.graph, this.graphGenerationState.generatedEntities, this.editorStore.graphManagerState.generationsBuildState, {}, generation_buildReport);
            // report
            stopWatch.record(GRAPH_MANAGER_EVENT.INITIALIZE_GRAPH__SUCCESS);
            const graphBuilderReportData = {
                timings: this.editorStore.applicationStore.timeService.finalizeTimingsRecord(stopWatch),
                dependencies: dependency_buildReport,
                dependenciesCount: this.editorStore.graphManagerState.graph.dependencyManager
                    .numberOfDependencies,
                graph: graph_buildReport,
                generations: generation_buildReport,
                generationsCount: this.graphGenerationState.generatedEntities.size,
            };
            LegendStudioTelemetryHelper.logEvent_GraphInitializationSucceeded(this.editorStore.applicationStore.telemetryService, graphBuilderReportData);
            this.editorStore.applicationStore.logService.info(LogEvent.create(GRAPH_MANAGER_EVENT.INITIALIZE_GRAPH__SUCCESS), graphBuilderReportData);
            // add generation specification if model generation elements exists in graph and no generation specification
            yield flowResult(this.graphGenerationState.possiblyAddMissingGenerationSpecifications());
            return {
                status: GraphBuilderStatus.SUCCEEDED,
            };
        }
        catch (error) {
            assertErrorThrown(error);
            this.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.GRAPH_BUILDER_FAILURE), error);
            if (error instanceof DependencyGraphBuilderError) {
                this.editorStore.graphManagerState.graphBuildState.fail();
                // no recovery if dependency models cannot be built, this makes assumption that all dependencies models are compiled successfully
                // TODO: we might want to handle this more gracefully when we can show people the dependency model element in the future
                this.editorStore.applicationStore.notificationService.notifyError(`Can't initialize dependency models. Error: ${error.message}`);
                const projectConfigurationEditorState = this.editorStore.projectConfigurationEditorState;
                projectConfigurationEditorState.setSelectedTab(CONFIGURATION_EDITOR_TAB.PROJECT_DEPENDENCIES);
                this.editorStore.tabManagerState.openTab(projectConfigurationEditorState);
            }
            else if (error instanceof GraphDataDeserializationError) {
                // if something goes wrong with de-serialization, redirect to model importer to fix
                this.redirectToModelImporterForDebugging(error);
            }
            else if (error instanceof NetworkClientError) {
                this.editorStore.graphManagerState.graphBuildState.fail();
                this.editorStore.applicationStore.notificationService.notifyWarning(`Can't build graph. Error: ${error.message}`);
            }
            else {
                // TODO: we should split this into 2 notifications when we support multiple notifications
                this.editorStore.applicationStore.notificationService.notifyError(`Can't build graph. Redirected to text mode for debugging. Error: ${error.message}`);
                this.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.GRAPH_BUILDER_FAILURE), error);
                try {
                    yield flowResult(this.editorStore.switchModes(GRAPH_EDITOR_MODE.GRAMMAR_TEXT, {
                        isGraphBuildFailure: true,
                    }));
                }
                catch (error2) {
                    assertErrorThrown(error2);
                    this.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.GRAPH_BUILDER_FAILURE), error2);
                    if (error2 instanceof NetworkClientError) {
                        // in case the server cannot even transform the JSON due to corrupted protocol, we can redirect to model importer
                        this.redirectToModelImporterForDebugging(error2);
                        return {
                            status: GraphBuilderStatus.FAILED,
                            error: error2,
                        };
                    }
                    if (error2 instanceof Error) {
                        return {
                            status: GraphBuilderStatus.FAILED,
                            error: error2,
                        };
                    }
                }
                return {
                    status: GraphBuilderStatus.REDIRECTED_TO_TEXT_MODE,
                    error,
                };
            }
            return {
                status: GraphBuilderStatus.FAILED,
                error,
            };
        }
        finally {
            this.isInitializingGraph = false;
        }
    }
    *buildGraphForLazyText() {
        this.isInitializingGraph = true;
        const stopWatch = new StopWatch();
        // reset
        this.editorStore.graphManagerState.resetGraph();
        // fetch and build dependencies
        stopWatch.record();
        const dependencyManager = this.editorStore.graphManagerState.graphManager.createDependencyManager();
        this.editorStore.graphManagerState.graph.dependencyManager =
            dependencyManager;
        this.editorStore.graphManagerState.dependenciesBuildState.setMessage(`Fetching dependencies...`);
        const dependencyEntitiesIndex = (yield flowResult(this.getIndexedDependencyEntities()));
        stopWatch.record(GRAPH_MANAGER_EVENT.FETCH_GRAPH_DEPENDENCIES__SUCCESS);
        dependencyManager.initialize(dependencyEntitiesIndex);
        // set dependency manager graph origin to entities
        if (dependencyManager.origin === undefined) {
            dependencyManager.setOrigin(new GraphEntities(Array.from(dependencyEntitiesIndex.values())
                .map((e) => e.entities)
                .flat()));
        }
        this.isInitializingGraph = false;
        this.editorStore.graphManagerState.dependenciesBuildState.sync(ActionState.create().pass());
    }
    redirectToModelImporterForDebugging(error) {
        if (this.editorStore.isInConflictResolutionMode) {
            this.editorStore.applicationStore.alertService.setBlockingAlert({
                message: `Can't de-serialize graph model from entities`,
                prompt: `Please refresh the application and abort conflict resolution`,
            });
            return;
        }
        this.editorStore.applicationStore.notificationService.notifyWarning(`Can't de-serialize graph model from entities. Redirected to model importer for debugging. Error: ${error.message}`);
        const nativeImporterState = this.editorStore.modelImporterState.setNativeImportType(MODEL_IMPORT_NATIVE_INPUT_TYPE.ENTITIES);
        // Making an async call
        nativeImporterState.loadCurrentProjectEntities();
        this.editorStore.tabManagerState.openTab(this.editorStore.modelImporterState);
    }
    /**
     * Loads entity changes to graph and updates application.
     */
    *loadEntityChangesToGraph(changes, baseEntities) {
        try {
            assertTrue(this.editorStore.graphEditorMode.mode === GRAPH_EDITOR_MODE.FORM, `Can't apply entity changes: operation only supported in form mode`);
            const entities = baseEntities ??
                this.editorStore.graphManagerState.graph.allOwnElements.map((element) => this.editorStore.graphManagerState.graphManager.elementToEntity(element));
            const modifiedEntities = applyEntityChanges(entities, changes);
            yield flowResult(this.editorStore.graphEditorMode.updateGraphAndApplication(modifiedEntities));
        }
        catch (error) {
            assertErrorThrown(error);
            this.editorStore.applicationStore.notificationService.notifyError(`Can't load entity changes: ${error.message}`);
        }
    }
    /**
     * NOTE: this can post memory-leak issue if we start having immutable elements referencing current graph elements:
     * e.g. subclass analytics on the immutable class, etc.
     *
     * @risk memory-leak
     */
    *rebuildDependencies(newGraph) {
        if (this.editorStore.graphManagerState.dependenciesBuildState.hasSucceeded) {
            newGraph.dependencyManager =
                this.editorStore.graphManagerState.graph.dependencyManager;
        }
        else {
            this.editorStore.projectConfigurationEditorState.setProjectConfiguration(ProjectConfiguration.serialization.fromJson((yield this.editorStore.sdlcServerClient.getConfiguration(this.editorStore.sdlcState.activeProject.projectId, this.editorStore.sdlcState.activeWorkspace))));
            const dependencyManager = this.editorStore.graphManagerState.graphManager.createDependencyManager();
            newGraph.dependencyManager = dependencyManager;
            const dependenciesBuildState = ActionState.create();
            yield this.editorStore.graphManagerState.graphManager.buildDependencies(this.editorStore.graphManagerState.coreModel, this.editorStore.graphManagerState.systemModel, dependencyManager, (yield flowResult(this.getIndexedDependencyEntities())), dependenciesBuildState);
            // NOTE: here we don't want to modify the current graph build state directly
            // instead, we quietly run this in the background and then sync it with the current build state
            this.editorStore.graphManagerState.dependenciesBuildState.sync(dependenciesBuildState);
        }
    }
    /**
     * Used to update generation model and generation graph using the generated entities
     * does not alter the main or dependency model
     */
    *updateGenerationGraphAndApplication() {
        assertTrue(this.editorStore.graphManagerState.graphBuildState.hasSucceeded &&
            this.editorStore.graphManagerState.dependenciesBuildState.hasSucceeded, 'Both main model and dependencies must be processed to built generation graph');
        this.isUpdatingApplication = true;
        try {
            this.editorStore.tabManagerState.cacheAndClose({ cacheGeneration: true });
            yield flowResult(this.editorStore.graphManagerState.graph.generationModel.dispose());
            // we reset the generation model
            this.editorStore.graphManagerState.graph.generationModel =
                this.editorStore.graphManagerState.graphManager.createGenerationModel();
            yield this.editorStore.graphManagerState.graphManager.buildGenerations(this.editorStore.graphManagerState.graph, this.graphGenerationState.generatedEntities, this.editorStore.graphManagerState.generationsBuildState);
            this.editorStore.explorerTreeState.reprocess();
            this.editorStore.tabManagerState.recoverTabs();
        }
        catch (error) {
            assertErrorThrown(error);
            this.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.GRAPH_BUILDER_FAILURE), error);
            this.editorStore.applicationStore.notificationService.notifyError(`Can't build graph: ${error.message}`);
        }
        finally {
            this.isUpdatingApplication = false;
        }
    }
    async getIndexedDependencyEntities(dependencyReport) {
        const dependencyEntitiesIndex = new Map();
        const currentConfiguration = this.editorStore.projectConfigurationEditorState
            .currentProjectConfiguration;
        try {
            if (currentConfiguration.projectDependencies.length) {
                const dependencyCoordinates = await this.buildProjectDependencyCoordinates(currentConfiguration.projectDependencies);
                // NOTE: if A@v1 is transitive dependencies of 2 or more
                // direct dependencies, metadata server will take care of deduplication
                const dependencyEntitiesJson = await this.editorStore.depotServerClient.collectDependencyEntities(dependencyCoordinates.map((e) => ProjectDependencyCoordinates.serialization.toJson(e)), true, true);
                const dependencyEntities = dependencyEntitiesJson.map((e) => ProjectVersionEntities.serialization.fromJson(e));
                const dependencyProjects = new Map();
                dependencyEntities.forEach((dependencyInfo) => {
                    const projectId = dependencyInfo.id;
                    // There are a few validations that must be done:
                    // 1. Unlike above, if in the depdendency graph, we have both A@v1 and A@v2
                    //    then we need to throw. Both SDLC and metadata server should handle this
                    //    validation, but haven't, so for now, we can do that in Studio.
                    // 2. Same as the previous case, but for version-to-version transformation
                    //    This is a special case that needs handling, right now, SDLC does auto
                    //    healing, by scanning all the path and convert them into versioned path
                    //    e.g. model::someClass -> project1::v1_0_0::model::someClass
                    //    But this is a rare and advanced use-case which we will not attempt to handle now.
                    if (dependencyProjects.has(projectId)) {
                        dependencyProjects.get(projectId)?.add(dependencyInfo.versionId);
                    }
                    else {
                        dependencyProjects.set(dependencyInfo.id, new Set([dependencyInfo.versionId]));
                    }
                    dependencyEntitiesIndex.set(dependencyInfo.id, new EntitiesWithOrigin(dependencyInfo.groupId, dependencyInfo.artifactId, dependencyInfo.versionId, dependencyInfo.entities));
                });
                const hasConflicts = Array.from(dependencyProjects.entries()).find(([k, v]) => v.size > 1);
                if (hasConflicts) {
                    let dependencyInfo = dependencyReport;
                    if (!dependencyInfo) {
                        // No dependency report was provided, need to fetch it
                        try {
                            const dependencyTree = await this.editorStore.depotServerClient.analyzeDependencyTree(dependencyCoordinates.map((e) => ProjectDependencyCoordinates.serialization.toJson(e)));
                            const rawReport = RawProjectDependencyReport.serialization.fromJson(dependencyTree);
                            dependencyInfo = buildDependencyReport(rawReport);
                        }
                        catch (error) {
                            assertErrorThrown(error);
                            this.editorStore.applicationStore.logService.error(LogEvent.create(LEGEND_STUDIO_APP_EVENT.DEPOT_MANAGER_FAILURE), error);
                        }
                    }
                    else {
                    }
                    const startErrorMessage = 'Depending on multiple versions of a project is not supported. Found conflicts:\n';
                    if (dependencyInfo?.conflicts.length) {
                        const conflictingProjects = dependencyInfo.conflicts
                            .map((c) => `project: ${c.groupId}:${c.artifactId}\nversions:[${c.versions
                            .map((v) => v.versionId)
                            .join(',')}]`)
                            .join('\n');
                        throw new UnsupportedOperationError(startErrorMessage + conflictingProjects);
                    }
                    else {
                        const conflictMessages = Array.from(dependencyProjects.entries())
                            .filter(([, v]) => v.size > 1)
                            .map(([k, v]) => `project: ${k}\n versions: ${Array.from(v.values()).join(',')}`)
                            .join('\n\n');
                        throw new UnsupportedOperationError(startErrorMessage + conflictMessages);
                    }
                }
            }
        }
        catch (error) {
            assertErrorThrown(error);
            const message = `Can't acquire dependency entitites. Error: ${error.message}`;
            this.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.GRAPH_BUILDER_FAILURE), message);
            this.editorStore.applicationStore.notificationService.notifyError(error);
            throw new DependencyGraphBuilderError(error);
        }
        return dependencyEntitiesIndex;
    }
    async buildProjectDependencyCoordinates(projectDependencies) {
        return Promise.all(projectDependencies.map(async (dep) => {
            const exclusionCoordinates = (dep.exclusions ?? []).map((exclusion) => ({
                groupId: guaranteeNonNullable(exclusion.groupId),
                artifactId: guaranteeNonNullable(exclusion.artifactId),
            }));
            return Promise.resolve(new ProjectDependencyCoordinates(guaranteeNonNullable(dep.groupId), guaranteeNonNullable(dep.artifactId), dep.versionId, exclusionCoordinates.length > 0 ? exclusionCoordinates : undefined));
        }));
    }
    // -------------------------------------------------- UTILITIES -----------------------------------------------------
    getPackageableElementType(element) {
        if (element instanceof PrimitiveType) {
            return PACKAGEABLE_ELEMENT_TYPE.PRIMITIVE;
        }
        else if (element instanceof Package) {
            return PACKAGEABLE_ELEMENT_TYPE.PACKAGE;
        }
        else if (element instanceof Class) {
            return PACKAGEABLE_ELEMENT_TYPE.CLASS;
        }
        else if (element instanceof Association) {
            return PACKAGEABLE_ELEMENT_TYPE.ASSOCIATION;
        }
        else if (element instanceof Enumeration) {
            return PACKAGEABLE_ELEMENT_TYPE.ENUMERATION;
        }
        else if (element instanceof Measure) {
            return PACKAGEABLE_ELEMENT_TYPE.MEASURE;
        }
        else if (element instanceof Unit) {
            return PACKAGEABLE_ELEMENT_TYPE.UNIT;
        }
        else if (element instanceof Profile) {
            return PACKAGEABLE_ELEMENT_TYPE.PROFILE;
        }
        else if (element instanceof ConcreteFunctionDefinition) {
            return PACKAGEABLE_ELEMENT_TYPE.FUNCTION;
        }
        else if (element instanceof FlatData) {
            return PACKAGEABLE_ELEMENT_TYPE.FLAT_DATA_STORE;
        }
        else if (element instanceof Database) {
            return PACKAGEABLE_ELEMENT_TYPE.DATABASE;
        }
        else if (element instanceof Mapping) {
            return PACKAGEABLE_ELEMENT_TYPE.MAPPING;
        }
        else if (element instanceof Service) {
            return PACKAGEABLE_ELEMENT_TYPE.SERVICE;
        }
        else if (element instanceof PackageableConnection) {
            return PACKAGEABLE_ELEMENT_TYPE.CONNECTION;
        }
        else if (element instanceof PackageableRuntime) {
            return PACKAGEABLE_ELEMENT_TYPE.RUNTIME;
        }
        else if (element instanceof FileGenerationSpecification) {
            return PACKAGEABLE_ELEMENT_TYPE.FILE_GENERATION;
        }
        else if (element instanceof GenerationSpecification) {
            return PACKAGEABLE_ELEMENT_TYPE.GENERATION_SPECIFICATION;
        }
        else if (element instanceof SectionIndex) {
            return PACKAGEABLE_ELEMENT_TYPE.SECTION_INDEX;
        }
        else if (element instanceof DataElement) {
            return PACKAGEABLE_ELEMENT_TYPE.DATA;
        }
        else if (element instanceof ExecutionEnvironmentInstance) {
            return PACKAGEABLE_ELEMENT_TYPE.EXECUTION_ENVIRONMENT;
        }
        else if (element instanceof SnowflakeApp) {
            return PACKAGEABLE_ELEMENT_TYPE.SNOWFLAKE_APP;
        }
        else if (element instanceof SnowflakeM2MUdf) {
            return PACKAGEABLE_ELEMENT_TYPE.SNOWFLAKE_M2M_UDF;
        }
        else if (element instanceof HostedService) {
            return PACKAGEABLE_ELEMENT_TYPE.HOSTED_SERVICE;
        }
        else if (element instanceof DataProduct) {
            return PACKAGEABLE_ELEMENT_TYPE._DATA_PRODUCT;
        }
        else if (element instanceof IngestDefinition) {
            return PACKAGEABLE_ELEMENT_TYPE.INGEST_DEFINITION;
        }
        else if (element instanceof MemSQLFunction) {
            return PACKAGEABLE_ELEMENT_TYPE.MEM_SQL_FUNCTION;
        }
        const extraElementTypeLabelGetters = this.editorStore.pluginManager
            .getApplicationPlugins()
            .flatMap((plugin) => plugin.getExtraElementClassifiers?.() ?? []);
        for (const labelGetter of extraElementTypeLabelGetters) {
            const label = labelGetter(element);
            if (label) {
                return label;
            }
        }
        return PACKAGEABLE_ELEMENT_TYPE.INTERNAL__UnknownElement;
    }
}
//# sourceMappingURL=EditorGraphState.js.map