<commit_before>/**
 * @license
 * Copyright 2017 JBoss Inc
 *
 * 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 {
    Component,
    EventEmitter,
    Input,
    OnChanges,
    Output,
    SimpleChanges,
    ViewChild,
    ViewEncapsulation
} from "@angular/core";
import {ApiDefinition} from "../../../../models/api.model";
import {
    Oas20ResponseDefinition,
    Oas20SchemaDefinition,
    Oas30ResponseDefinition,
    Oas30SchemaDefinition,
    OasDocument,
    OasLibraryUtils,
    OasNode,
    OasOperation,
    OasPathItem,
    OasTraverserDirection,
    OasValidationError,
    OasVisitorUtil
} from "oai-ts-core";
import {EditorMasterComponent} from "./_components/master.component";
import {AbstractCombinedVisitorAdapter, AllNodeVisitor} from "./_visitors/base.visitor";
import {NodeSelectionEvent} from "./_events/node-selection.event";
import {ICommand, OtCommand, OtEngine} from "oai-ts-commands";
import {ApiDesignCommandAck} from "../../../../models/ack.model";
import {ApiEditorUser} from "../../../../models/editor-user.model";


@Component({
    moduleId: module.id,
    selector: "api-editor",
    templateUrl: "editor.component.html",
    styleUrls: ["editor.component.css", "editor.component.light.css", "editor.component.dark.css"],
    encapsulation: ViewEncapsulation.None
})
export class ApiEditorComponent implements OnChanges {

    @Input() api: ApiDefinition;
    @Output() onCommandExecuted: EventEmitter<OtCommand> = new EventEmitter<OtCommand>();
    @Output() onSelectionChanged: EventEmitter<string> = new EventEmitter<string>();

    private _library: OasLibraryUtils = new OasLibraryUtils();
    private _document: OasDocument = null;
    private _otEngine: OtEngine = null;

    theme: string = "light";

    private currentSelection: NodeSelectionEvent;
    public validationErrors: OasValidationError[] = [];

    @ViewChild("master") master: EditorMasterComponent;

    formType: string;

    /**
     * Constructor.
     */
    constructor() {}

    /**
     * Called when the @Input changes.
     * @param {SimpleChanges} changes
     */
    ngOnChanges(changes: SimpleChanges): void {
        this._document = null;
        if (this.document().getSpecVersion() === "2.0") {
            this.formType = "main_20";
        } else {
            this.formType = "main_30";
        }
        console.info("****** just set the form type to: %s", this.formType);
    }

    /**
     * Gets the OpenAPI spec as a document.
     */
    public document(): OasDocument {
        if (this._document === null) {
            this._document = this._library.createDocument(this.api.spec);
            this.validateModel();
        }
        return this._document;
    }

    /**
     * Lazy getter for the OtEngine.
     * @return {OtEngine}
     */
    public otEngine(): OtEngine {
        if (this._otEngine === null) {
            this._otEngine = new OtEngine(this.document());
        }
        return this._otEngine;
    }

    /**
     * Called whenever the user presses a key.
     * @param event
     */
    public onGlobalKeyDown(event: KeyboardEvent): void {
        // TODO skip any event that was sent to an input field (e.g. input, textarea, etc)
        if (event.ctrlKey && event.key === 'z' && !event.metaKey && !event.altKey) {
            console.info("[ApiEditorComponent] User wants to 'undo' the last command (not implemented).");
            // this._commands.undoLastCommand(this.document());
            // this.master.validateSelection();
            // this.validateModel();
        }
        if (event.ctrlKey && event.key === 'y' && !event.metaKey && !event.altKey) {
            console.info("[ApiEditorComponent] User wants to 'redo' the last command (not implemented).");
            // this._commands.redoLastCommand(this.document());
            // this.master.validateSelection();
            // this.validateModel();
        }
    }

    /**
     * Called when an editor component creates a command that should be executed.
     * @param command
     */
    public onCommand(command: ICommand): void {
        let otCmd: OtCommand = new OtCommand();
        otCmd.command = command;
        otCmd.contentVersion = Date.now();
        this.otEngine().executeCommand(otCmd, true);
        this.onCommandExecuted.emit(otCmd);

        // After changing the model, we should re-validate it
        this.validateModel();
    }

    /**
     * Executes a command.
     * @param {ICommand} command
     */
    public executeCommand(command: OtCommand): void {
        console.info("[ApiEditorComponent] Executing a command.");
        this.otEngine().executeCommand(command);
    }

    /**
     * Finalizes a command.
     * @param {ApiDesignCommandAck} ack
     */
    public finalizeCommand(ack: ApiDesignCommandAck): void {
        this.otEngine().finalizeCommand(ack.commandId, ack.contentVersion);
    }

    /**
     * Called to update the selection state of the given remote API editor (i.e. an active collaborator).
     * @param {ApiEditorUser} user
     * @param {string} selection
     */
    public updateCollaboratorSelection(user: ApiEditorUser, selection: string): void {
        this.master.updateCollaboratorSelection(user, selection);
    }

    /**
     * Called when the user selects a node in some way.<commit_msg>Deselect a path/operation/schema after deleting it.  Fixes #183<commit_after>/**
 * @license
 * Copyright 2017 JBoss Inc
 *
 * 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 {
    Component,
    EventEmitter,
    Input,
    OnChanges,
    Output,
    SimpleChanges,
    ViewChild,
    ViewEncapsulation
} from "@angular/core";
import {ApiDefinition} from "../../../../models/api.model";
import {
    Oas20ResponseDefinition,
    Oas20SchemaDefinition,
    Oas30ResponseDefinition,
    Oas30SchemaDefinition,
    OasDocument,
    OasLibraryUtils,
    OasNode,
    OasOperation,
    OasPathItem,
    OasTraverserDirection,
    OasValidationError,
    OasVisitorUtil
} from "oai-ts-core";
import {EditorMasterComponent} from "./_components/master.component";
import {AbstractCombinedVisitorAdapter, AllNodeVisitor} from "./_visitors/base.visitor";
import {NodeSelectionEvent} from "./_events/node-selection.event";
import {ICommand, OtCommand, OtEngine} from "oai-ts-commands";
import {ApiDesignCommandAck} from "../../../../models/ack.model";
import {ApiEditorUser} from "../../../../models/editor-user.model";


@Component({
    moduleId: module.id,
    selector: "api-editor",
    templateUrl: "editor.component.html",
    styleUrls: ["editor.component.css", "editor.component.light.css", "editor.component.dark.css"],
    encapsulation: ViewEncapsulation.None
})
export class ApiEditorComponent implements OnChanges {

    @Input() api: ApiDefinition;
    @Output() onCommandExecuted: EventEmitter<OtCommand> = new EventEmitter<OtCommand>();
    @Output() onSelectionChanged: EventEmitter<string> = new EventEmitter<string>();

    private _library: OasLibraryUtils = new OasLibraryUtils();
    private _document: OasDocument = null;
    private _otEngine: OtEngine = null;

    theme: string = "light";

    private currentSelection: NodeSelectionEvent;
    public validationErrors: OasValidationError[] = [];

    @ViewChild("master") master: EditorMasterComponent;

    formType: string;

    /**
     * Constructor.
     */
    constructor() {}

    /**
     * Called when the @Input changes.
     * @param {SimpleChanges} changes
     */
    ngOnChanges(changes: SimpleChanges): void {
        this._document = null;
        if (this.document().getSpecVersion() === "2.0") {
            this.formType = "main_20";
        } else {
            this.formType = "main_30";
        }
        console.info("****** just set the form type to: %s", this.formType);
    }

    /**
     * Gets the OpenAPI spec as a document.
     */
    public document(): OasDocument {
        if (this._document === null) {
            this._document = this._library.createDocument(this.api.spec);
            this.validateModel();
        }
        return this._document;
    }

    /**
     * Lazy getter for the OtEngine.
     * @return {OtEngine}
     */
    public otEngine(): OtEngine {
        if (this._otEngine === null) {
            this._otEngine = new OtEngine(this.document());
        }
        return this._otEngine;
    }

    /**
     * Called whenever the user presses a key.
     * @param event
     */
    public onGlobalKeyDown(event: KeyboardEvent): void {
        // TODO skip any event that was sent to an input field (e.g. input, textarea, etc)
        if (event.ctrlKey && event.key === 'z' && !event.metaKey && !event.altKey) {
            console.info("[ApiEditorComponent] User wants to 'undo' the last command (not implemented).");
            // this._commands.undoLastCommand(this.document());
            // this.master.validateSelection();
            // this.validateModel();
        }
        if (event.ctrlKey && event.key === 'y' && !event.metaKey && !event.altKey) {
            console.info("[ApiEditorComponent] User wants to 'redo' the last command (not implemented).");
            // this._commands.redoLastCommand(this.document());
            // this.master.validateSelection();
            // this.validateModel();
        }
    }

    /**
     * Called when an editor component creates a command that should be executed.
     * @param command
     */
    public onCommand(command: ICommand): void {
        let otCmd: OtCommand = new OtCommand();
        otCmd.command = command;
        otCmd.contentVersion = Date.now();
        this.otEngine().executeCommand(otCmd, true);
        this.onCommandExecuted.emit(otCmd);

        // After changing the model, we should re-validate it
        this.validateModel();
        // And also validate the current selection
        this.master.validateSelection();
    }

    /**
     * Executes a command.  Called by the parent of this component when detecting that
     * another user has executed a command.  In other words, this command is *not*
     * performed by the local user.
     * @param {ICommand} command
     */
    public executeCommand(command: OtCommand): void {
        console.info("[ApiEditorComponent] Executing a command.");
        this.otEngine().executeCommand(command);

        // After changing the model, we should re-validate it
        this.validateModel();
        // And also validate the current selection
        this.master.validateSelection();
    }

    /**
     * Finalizes a command.
     * @param {ApiDesignCommandAck} ack
     */
    public finalizeCommand(ack: ApiDesignCommandAck): void {
        this.otEngine().finalizeCommand(ack.commandId, ack.contentVersion);
    }

    /**
     * Called to update the selection state of the given remote API editor (i.e. an active collaborator).
     * @param {ApiEditorUser} user
     * @param {string} selection
     */
    public updateCollaboratorSelection(user: ApiEditorUser, selection: string): void {
        this.master.updateCollaboratorSelection(user, selection);
    }

    /**
     * Called when the user selects a node in some way.
{'fraction_non_alphanumeric': 0.119765908341576, 'fraction_numerical': 0.0038740520936366633, 'mean_word_length': 2.7206378411530205, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5108221', 'n_tokens_mistral': 3378, 'n_tokens_neox': 3329, 'n_words': 935}