import { __esDecorate, __runInitializers } from "tslib";
/* eslint-disable @typescript-eslint/ban-ts-comment */
/**
@license
Copyright 2018 The Advanced REST client authors <arc@mulesoft.com>
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 { html, nothing } from 'lit';
import { property, query } from 'lit/decorators.js';
import { assignTheme } from '../../monaco/theme.js';
import { detectLanguage } from '../../monaco/helper.js';
import * as ScrollHelper from '../../lib/ScrollHelper.js';
import { Events } from '../../events/Events.js';
import ApiElement from '../ApiElement.js';
/* global monaco */
let modelId = 0;
let BodyTextEditor = (() => {
    let _classSuper = ApiElement;
    let _instanceExtraInitializers = [];
    let _container_decorators;
    let _container_initializers = [];
    let _container_extraInitializers = [];
    let _set_value_decorators;
    let _set_contentType_decorators;
    let _set_readOnly_decorators;
    let _allowFormInfo_decorators;
    let _allowFormInfo_initializers = [];
    let _allowFormInfo_extraInitializers = [];
    return class BodyTextEditor extends _classSuper {
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            _container_decorators = [query('#container')];
            _set_value_decorators = [property({ type: String })];
            _set_contentType_decorators = [property({ type: String, reflect: true })];
            _set_readOnly_decorators = [property({ type: Boolean, reflect: true })];
            _allowFormInfo_decorators = [property({ type: Boolean })];
            __esDecorate(this, null, _container_decorators, { kind: "accessor", name: "container", static: false, private: false, access: { has: obj => "container" in obj, get: obj => obj.container, set: (obj, value) => { obj.container = value; } }, metadata: _metadata }, _container_initializers, _container_extraInitializers);
            __esDecorate(this, null, _set_value_decorators, { kind: "setter", name: "value", static: false, private: false, access: { has: obj => "value" in obj, set: (obj, value) => { obj.value = value; } }, metadata: _metadata }, null, _instanceExtraInitializers);
            __esDecorate(this, null, _set_contentType_decorators, { kind: "setter", name: "contentType", static: false, private: false, access: { has: obj => "contentType" in obj, set: (obj, value) => { obj.contentType = value; } }, metadata: _metadata }, null, _instanceExtraInitializers);
            __esDecorate(this, null, _set_readOnly_decorators, { kind: "setter", name: "readOnly", static: false, private: false, access: { has: obj => "readOnly" in obj, set: (obj, value) => { obj.readOnly = value; } }, metadata: _metadata }, null, _instanceExtraInitializers);
            __esDecorate(this, null, _allowFormInfo_decorators, { kind: "accessor", name: "allowFormInfo", static: false, private: false, access: { has: obj => "allowFormInfo" in obj, get: obj => obj.allowFormInfo, set: (obj, value) => { obj.allowFormInfo = value; } }, metadata: _metadata }, _allowFormInfo_initializers, _allowFormInfo_extraInitializers);
            if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
        }
        #container_accessor_storage = (__runInitializers(this, _instanceExtraInitializers), __runInitializers(this, _container_initializers, void 0));
        get container() { return this.#container_accessor_storage; }
        set container(value) { this.#container_accessor_storage = value; }
        modelUri = __runInitializers(this, _container_extraInitializers);
        valueInternal = '';
        /**
         * A HTTP body.
         * @attribute
         */
        get value() {
            return this.valueInternal;
        }
        set value(value) {
            const old = this.valueInternal;
            if (old === value) {
                return;
            }
            this.valueInternal = value || '';
            const { editor: e } = this;
            if (e) {
                e.setValue(value || '');
            }
        }
        contentTypeInternal;
        languageInternal;
        /**
         * The current language of the editor. It is set via the `contentType`.
         */
        get language() {
            return this.languageInternal;
        }
        readOnlyValue = false;
        /**
         * Uses the current content type to detect language support.
         * @attribute
         */
        get contentType() {
            return this.contentTypeInternal;
        }
        set contentType(value) {
            const old = this.contentTypeInternal;
            if (old === value) {
                return;
            }
            this.contentTypeInternal = value;
            const oldLang = this.languageInternal;
            const lang = detectLanguage(value);
            if (oldLang === lang) {
                return;
            }
            this.languageInternal = lang;
            this.setLanguage(lang);
        }
        /**
         * When set the editor is in read only mode.
         * @attribute
         */
        get readOnly() {
            return this.readOnlyValue;
        }
        set readOnly(value) {
            const old = this.readOnlyValue;
            if (old === value) {
                return;
            }
            this.readOnlyValue = value;
            this.setEditorConfigProperty('readOnly', value);
        }
        monacoInstance;
        get editor() {
            return this.monacoInstance;
        }
        validationSchemas;
        get schemas() {
            return this.validationSchemas;
        }
        set schemas(value) {
            const old = this.validationSchemas;
            if (old === value) {
                return;
            }
            this.validationSchemas = value;
            this.updateEditorSchemas(value);
        }
        observer;
        #allowFormInfo_accessor_storage = __runInitializers(this, _allowFormInfo_initializers, void 0);
        /**
         * @attribute
         */
        get allowFormInfo() { return this.#allowFormInfo_accessor_storage; }
        set allowFormInfo(value) { this.#allowFormInfo_accessor_storage = value; }
        constructor() {
            super();
            this.valueChanged = this.valueChanged.bind(this);
            this.observer = new ResizeObserver(this.handleObservedResize.bind(this));
        }
        connectedCallback() {
            super.connectedCallback();
            ScrollHelper.addListeners(this, this.resizeHandler.bind(this));
            const { container } = this;
            if (container) {
                this.observer.observe(container);
            }
        }
        disconnectedCallback() {
            super.disconnectedCallback();
            ScrollHelper.removeListeners(this);
            this.editor?.dispose();
            const { container } = this;
            if (container) {
                this.observer.unobserve(container);
            }
        }
        firstUpdated() {
            const config = this.generateEditorConfig();
            const node = this.container;
            // @ts-ignore
            const instance = monaco.editor.create(node, config);
            // instance.onDidChangeModelContent(this.valueChanged);
            // We use `onDidBlurEditorText` which is the closest we can get to an input's
            // `change` event. This will reduce the number of updates on the parent
            // editor.
            instance.onDidBlurEditorText(this.valueChanged);
            this.monacoInstance = instance;
            this.setupActions(instance);
            this.observer.observe(node);
        }
        refreshDebouncer = __runInitializers(this, _allowFormInfo_extraInitializers);
        /**
         * Handler for the `resize` event provided by the resizable mixin.
         */
        resizeHandler() {
            if (this.refreshDebouncer) {
                clearTimeout(this.refreshDebouncer);
            }
            this.refreshDebouncer = setTimeout(this.refreshEditor.bind(this));
        }
        /**
         * A function that is called from the `[resizeHandler]` in a timeout to reduce the number
         * of computations during the application initialization, where it can receive hundreds of
         * the `resize` events.
         */
        refreshEditor() {
            this.refreshDebouncer = undefined;
            if (!this.monacoInstance) {
                return;
            }
            this.monacoInstance.layout();
        }
        /**
         * @param lang New language to set
         */
        setLanguage(lang) {
            const { editor: e } = this;
            if (!e || !lang) {
                return;
            }
            const model = e.getModel();
            if (model) {
                // @ts-ignore
                monaco.editor.setModelLanguage(model, lang);
            }
        }
        /**
         * Sets up editor actions
         */
        setupActions(inst) {
            inst.addAction({
                id: 'send-http-request',
                label: 'Send request',
                keybindings: [
                    // @ts-ignore
                    monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter,
                ],
                precondition: undefined,
                keybindingContext: undefined,
                contextMenuGroupId: 'navigation',
                contextMenuOrder: 1.5,
                run: () => {
                    Events.Http.Request.send(this);
                },
            });
        }
        changeTimeout;
        valueChanged() {
            const { editor: ed } = this;
            if (!ed) {
                return;
            }
            const editorValue = ed.getValue();
            if (editorValue === this.valueInternal) {
                return;
            }
            this.valueInternal = editorValue;
            if (this.changeTimeout) {
                // window.clearTimeout(this[changeTimeout]);
                window.cancelAnimationFrame(this.changeTimeout);
            }
            this.changeTimeout = window.requestAnimationFrame(() => {
                this.notifyChange();
            });
        }
        /**
         * Generates Monaco configuration
         */
        generateEditorConfig() {
            const { value = '', readOnly, languageInternal: language } = this;
            // @ts-ignore
            this.modelUri = monaco.Uri.parse(`http://raw-editor/model${++modelId}.json`);
            // @ts-ignore
            const model = monaco.editor.createModel(value, language || 'json', this.modelUri);
            const schemas = this.getCurrentSchemas();
            this.updateEditorSchemas(schemas);
            let config = {
                minimap: {
                    enabled: false,
                },
                readOnly,
                formatOnType: true,
                folding: true,
                tabSize: 2,
                detectIndentation: true,
                // value,
                // automaticLayout: true,
                model,
                padding: { top: 0, bottom: 0 },
                scrollBeyondLastLine: false,
                foldingHighlight: true,
                selectionHighlight: true,
            };
            // @ts-ignore
            config = assignTheme(monaco, config);
            if (language) {
                config.language = language;
            }
            return config;
        }
        getCurrentSchemas() {
            const { schemas } = this;
            if (Array.isArray(schemas) && schemas.length) {
                schemas[0].fileMatch = [this.modelUri?.toString() || ''];
                return schemas;
            }
            return [this.createDefaultSchema()];
        }
        createDefaultSchema() {
            const schema = {
                uri: 'http://raw-editor/default-schema.json',
                fileMatch: [this.modelUri?.toString() || ''],
                schema: {},
            };
            return schema;
        }
        updateEditorSchemas(schemas) {
            if (!this.modelUri || !schemas) {
                // the editor is not yet ready. This will be called again when it is ready.
                return;
            }
            let value = schemas;
            if (!Array.isArray(value) || !value.length) {
                value = [this.createDefaultSchema()];
            }
            else {
                value[0] = { ...value[0], fileMatch: [this.modelUri.toString()] };
            }
            // @ts-ignore
            monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
                validate: true,
                schemas: value,
            });
        }
        /**
         * @param prop The property to set
         */
        setEditorConfigProperty(prop, value) {
            const { editor: e } = this;
            if (!e) {
                return;
            }
            const opts = {
                [prop]: value,
            };
            e.updateOptions(opts);
        }
        handleObservedResize(entries) {
            const { editor: e } = this;
            if (!e) {
                return;
            }
            const [entry] = entries;
            const rect = entry.contentRect;
            e.layout({ height: rect.height, width: rect.width });
        }
        render() {
            return html `
      <div id="container"></div>
      ${this.renderFormInfo()}
    `;
        }
        renderFormInfo() {
            if (!this.allowFormInfo) {
                return nothing;
            }
            return html `
      <p class="form-info">
        Note that the content-type header will be added when the request is sent. We encourage you to use variables to
        insert sensitive data.
      </p>
    `;
        }
    };
})();
export default BodyTextEditor;
//# sourceMappingURL=BodyTextEditor.js.map