/**
 * 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, computed, makeObservable } from 'mobx';
import { ELEMENT_NATIVE_VIEW_MODE } from '../../EditorConfig.js';
import { EditorState } from '../../editor-state/EditorState.js';
import { LogEvent, assertErrorThrown, guaranteeNonNullable, guaranteeType, isType, } from '@finos/legend-shared';
import { GRAPH_MANAGER_EVENT, isElementReadOnly, INTERNAL__UnknownElement, } from '@finos/legend-graph';
import { DEFAULT_TAB_SIZE } from '@finos/legend-application';
const generateMultiLineCommentForError = (message, error) => `/**\n * ${message}. Error: ${error.message.replace(/\n/gu, '\n * ')}\n */`;
export var ELEMENT_GENERATION_MODE;
(function (ELEMENT_GENERATION_MODE) {
    ELEMENT_GENERATION_MODE["FILE_GENERATION"] = "FILE_GENERATION";
    ELEMENT_GENERATION_MODE["EXTERNAL_FORMAT"] = "EXTERNAL_FORMAT";
})(ELEMENT_GENERATION_MODE || (ELEMENT_GENERATION_MODE = {}));
export class ElementGenerationModeState {
    elementEditorState;
    editorStore;
    constructor(editorStore, elementEditorState) {
        this.elementEditorState = elementEditorState;
        this.editorStore = editorStore;
    }
}
export class ExternalFormatElementGenerationViewModeState extends ElementGenerationModeState {
    generationState;
    constructor(editorStore, elementEditorState, generationState) {
        super(editorStore, elementEditorState);
        this.generationState = generationState;
    }
    get label() {
        return this.generationState.description.name;
    }
}
export class FileGenerationViewModeState extends ElementGenerationModeState {
    elementGenerationState;
    constructor(editorStore, elementEditorState, elementGenerationState) {
        super(editorStore, elementEditorState);
        this.elementGenerationState = elementGenerationState;
    }
    get label() {
        return this.editorStore.graphState.graphGenerationState.globalFileGenerationState.getFileGenerationConfiguration(this.elementGenerationState.fileGenerationType).label;
    }
}
export class ElementEditorState extends EditorState {
    element;
    editMode = ELEMENT_NATIVE_VIEW_MODE.FORM;
    generationModeState;
    textContent = '';
    isReadOnly = false;
    constructor(editorStore, element, config) {
        super(editorStore);
        makeObservable(this, {
            element: observable,
            editMode: observable,
            textContent: observable,
            isReadOnly: observable,
            generationModeState: observable,
            label: computed,
            description: computed,
            elementPath: computed,
            setTextContent: action,
            setEditMode: action,
            changeGenerationModeState: action,
            generateElementProtocol: action,
            generateElementGrammar: flow,
        });
        this.element = element;
        this.isReadOnly =
            isElementReadOnly(element) || editorStore.disableGraphEditing;
    }
    get label() {
        return this.element.name;
    }
    get elementPath() {
        return this.element.path;
    }
    get description() {
        return this.element.path;
    }
    match(tab) {
        return tab instanceof ElementEditorState && tab.element === this.element;
    }
    setTextContent(text) {
        this.textContent = text;
    }
    setEditMode(mode) {
        this.editMode = mode;
        // changing edit mode will clear any existing generation view mode
        // as edit mode always takes precedence
        this.setGenerationModeState(undefined);
    }
    setGenerationModeState(state) {
        this.generationModeState = state;
    }
    changeGenerationModeState(mode, type) {
        if (type === ELEMENT_GENERATION_MODE.FILE_GENERATION) {
            const elementGenerationState = this.editorStore.elementGenerationStates.find((state) => state.fileGenerationType === mode);
            this.setGenerationModeState(new FileGenerationViewModeState(this.editorStore, this, guaranteeNonNullable(elementGenerationState)));
        }
        else {
            const xt = this.editorStore.graphState.graphGenerationState.externalFormatState.schemaGenerationStates.find((e) => e.description.name === mode);
            this.setGenerationModeState(new ExternalFormatElementGenerationViewModeState(this.editorStore, this, guaranteeNonNullable(xt)));
        }
    }
    generateElementProtocol() {
        try {
            const elementEntity = this.editorStore.graphManagerState.graphManager.elementToEntity(this.element, {
                pruneSourceInformation: true,
            });
            this.setTextContent(JSON.stringify(elementEntity.content, undefined, DEFAULT_TAB_SIZE));
        }
        catch (error) {
            assertErrorThrown(error);
            const isUnknownEntity = isType(this.element, INTERNAL__UnknownElement);
            if (isUnknownEntity) {
                const unknownEntity = guaranteeType(this.element, INTERNAL__UnknownElement);
                this.setTextContent(JSON.stringify(unknownEntity.content, undefined, DEFAULT_TAB_SIZE));
            }
            else {
                this.setTextContent(generateMultiLineCommentForError(`Can't generate protocol JSON for element`, error));
            }
            this.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.PARSING_FAILURE), error);
        }
    }
    *generateElementGrammar() {
        try {
            const grammar = (yield this.editorStore.graphManagerState.graphManager.entitiesToPureCode([
                this.editorStore.graphManagerState.graphManager.elementToEntity(this.element),
            ], { pretty: true }));
            this.setTextContent(grammar);
        }
        catch (error) {
            assertErrorThrown(error);
            this.setTextContent(generateMultiLineCommentForError(`Can't generate grammar text for element`, error));
            this.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.PARSING_FAILURE), error);
        }
    }
    /**
     * Takes the compilation and based on its source information, attempts to reveal the error
     * in the editor. The return values indicates if the editor has revealed the error successfully or not.
     */
    revealCompilationError(compilationError) {
        return false;
    }
    clearCompilationError() {
        return;
    }
    onOpen() {
        this.editorStore.explorerTreeState.openNode(this.element);
    }
}
//# sourceMappingURL=ElementEditorState.js.map