import { __esDecorate, __runInitializers } from "tslib";
import { html, nothing } from 'lit';
import { property, state } from 'lit/decorators.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { HttpRequest } from '@api-client/core/models/HttpRequest.js';
import { RequestAuthorization } from '@api-client/core/models/RequestAuthorization.js';
import { RequestConfig } from '@api-client/core/models/RequestConfig.js';
import { PayloadSerializer } from '@api-client/core/lib/transformers/PayloadSerializer.js';
import { SecurityProcessor } from '@api-client/core/authorization/lib/SecurityProcessor.js';
import { Events as CoreEvents } from '@api-client/core/events/Events.js';
import { EventTypes } from '../../events/EventTypes.js';
import { Events } from '../../events/Events.js';
import ApiElement from '../ApiElement.js';
import { authTypeToLabel } from '../authorization/AuthLabels.js';
import '../../md/icons/ui-icon.js';
import '../../define/http/http-url-input.js';
import '../../define/http/http-url-params-form.js';
import '../../define/http/http-headers-form.js';
import '../../define/http/http-snippets.js';
import '../../define/http/http-body-editor.js';
import '../../define/http/http-assertions.js';
import '../../define/http/http-flows.js';
import '../../define/http/http-request-config.js';
import '../../md/dropdown-list/ui-dropdown-list.js';
import '../../md/list/ui-list.js';
import '../../md/list/ui-list-item.js';
import '../../md/button/ui-button.js';
import '../../md/tabs/ui-tabs.js';
import '../../md/tabs/ui-tab.js';
import '../../md/divider/ui-divider.js';
import '../../md/dialog/ui-dialog.js';
import '../../define/authorization/basic-authorization.js';
import '../../define/authorization/bearer-authorization.js';
import '../../define/authorization/ntlm-authorization.js';
import '../../define/authorization/apikey-authorization.js';
import '../../define/authorization/oauth2-authorization.js';
import '../../define/authorization/oidc-authorization.js';
import '../../define/authorization/cc-authorization.js';
export const HttpMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'CONNECT', 'OPTIONS', 'TRACE'];
export const NonPayloadMethods = ['GET', 'HEAD'];
let RequestEditor = (() => {
    let _classSuper = ApiElement;
    let _readingPayload_decorators;
    let _readingPayload_initializers = [];
    let _readingPayload_extraInitializers = [];
    let _request_decorators;
    let _request_initializers = [];
    let _request_extraInitializers = [];
    let _payload_decorators;
    let _payload_initializers = [];
    let _payload_extraInitializers = [];
    let _contentType_decorators;
    let _contentType_initializers = [];
    let _contentType_extraInitializers = [];
    let _authorization_decorators;
    let _authorization_initializers = [];
    let _authorization_extraInitializers = [];
    let _assertions_decorators;
    let _assertions_initializers = [];
    let _assertions_extraInitializers = [];
    let _flows_decorators;
    let _flows_initializers = [];
    let _flows_extraInitializers = [];
    let _oauth2RedirectUri_decorators;
    let _oauth2RedirectUri_initializers = [];
    let _oauth2RedirectUri_extraInitializers = [];
    let _readOnly_decorators;
    let _readOnly_initializers = [];
    let _readOnly_extraInitializers = [];
    let _oauth2AuthorizationUri_decorators;
    let _oauth2AuthorizationUri_initializers = [];
    let _oauth2AuthorizationUri_extraInitializers = [];
    let _oauth2AccessTokenUri_decorators;
    let _oauth2AccessTokenUri_initializers = [];
    let _oauth2AccessTokenUri_extraInitializers = [];
    let _ignoreContentOnGet_decorators;
    let _ignoreContentOnGet_initializers = [];
    let _ignoreContentOnGet_extraInitializers = [];
    let _contentHeadersDialogOpened_decorators;
    let _contentHeadersDialogOpened_initializers = [];
    let _contentHeadersDialogOpened_extraInitializers = [];
    let _loading_decorators;
    let _loading_initializers = [];
    let _loading_extraInitializers = [];
    let _selectedTab_decorators;
    let _selectedTab_initializers = [];
    let _selectedTab_extraInitializers = [];
    let _ui_decorators;
    let _ui_initializers = [];
    let _ui_extraInitializers = [];
    let _config_decorators;
    let _config_initializers = [];
    let _config_extraInitializers = [];
    let _snippets_decorators;
    let _snippets_initializers = [];
    let _snippets_extraInitializers = [];
    return class RequestEditor extends _classSuper {
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            _readingPayload_decorators = [state()];
            _request_decorators = [property({ type: Object })];
            _payload_decorators = [state()];
            _contentType_decorators = [state()];
            _authorization_decorators = [property({ type: Array })];
            _assertions_decorators = [property({ type: Array })];
            _flows_decorators = [property({ type: Array })];
            _oauth2RedirectUri_decorators = [property({ type: String })];
            _readOnly_decorators = [property({ type: Boolean, reflect: true })];
            _oauth2AuthorizationUri_decorators = [property({ type: String, reflect: true })];
            _oauth2AccessTokenUri_decorators = [property({ type: String, reflect: true })];
            _ignoreContentOnGet_decorators = [property({ type: Boolean, reflect: true })];
            _contentHeadersDialogOpened_decorators = [property({ type: Boolean, reflect: true })];
            _loading_decorators = [property({ type: Boolean, reflect: true })];
            _selectedTab_decorators = [property({ type: String, reflect: true })];
            _ui_decorators = [property({ type: Object })];
            _config_decorators = [property({ type: Object })];
            _snippets_decorators = [state()];
            __esDecorate(this, null, _readingPayload_decorators, { kind: "accessor", name: "readingPayload", static: false, private: false, access: { has: obj => "readingPayload" in obj, get: obj => obj.readingPayload, set: (obj, value) => { obj.readingPayload = value; } }, metadata: _metadata }, _readingPayload_initializers, _readingPayload_extraInitializers);
            __esDecorate(this, null, _request_decorators, { kind: "accessor", name: "request", static: false, private: false, access: { has: obj => "request" in obj, get: obj => obj.request, set: (obj, value) => { obj.request = value; } }, metadata: _metadata }, _request_initializers, _request_extraInitializers);
            __esDecorate(this, null, _payload_decorators, { kind: "accessor", name: "payload", static: false, private: false, access: { has: obj => "payload" in obj, get: obj => obj.payload, set: (obj, value) => { obj.payload = value; } }, metadata: _metadata }, _payload_initializers, _payload_extraInitializers);
            __esDecorate(this, null, _contentType_decorators, { kind: "accessor", name: "contentType", static: false, private: false, access: { has: obj => "contentType" in obj, get: obj => obj.contentType, set: (obj, value) => { obj.contentType = value; } }, metadata: _metadata }, _contentType_initializers, _contentType_extraInitializers);
            __esDecorate(this, null, _authorization_decorators, { kind: "accessor", name: "authorization", static: false, private: false, access: { has: obj => "authorization" in obj, get: obj => obj.authorization, set: (obj, value) => { obj.authorization = value; } }, metadata: _metadata }, _authorization_initializers, _authorization_extraInitializers);
            __esDecorate(this, null, _assertions_decorators, { kind: "accessor", name: "assertions", static: false, private: false, access: { has: obj => "assertions" in obj, get: obj => obj.assertions, set: (obj, value) => { obj.assertions = value; } }, metadata: _metadata }, _assertions_initializers, _assertions_extraInitializers);
            __esDecorate(this, null, _flows_decorators, { kind: "accessor", name: "flows", static: false, private: false, access: { has: obj => "flows" in obj, get: obj => obj.flows, set: (obj, value) => { obj.flows = value; } }, metadata: _metadata }, _flows_initializers, _flows_extraInitializers);
            __esDecorate(this, null, _oauth2RedirectUri_decorators, { kind: "accessor", name: "oauth2RedirectUri", static: false, private: false, access: { has: obj => "oauth2RedirectUri" in obj, get: obj => obj.oauth2RedirectUri, set: (obj, value) => { obj.oauth2RedirectUri = value; } }, metadata: _metadata }, _oauth2RedirectUri_initializers, _oauth2RedirectUri_extraInitializers);
            __esDecorate(this, null, _readOnly_decorators, { kind: "accessor", name: "readOnly", static: false, private: false, access: { has: obj => "readOnly" in obj, get: obj => obj.readOnly, set: (obj, value) => { obj.readOnly = value; } }, metadata: _metadata }, _readOnly_initializers, _readOnly_extraInitializers);
            __esDecorate(this, null, _oauth2AuthorizationUri_decorators, { kind: "accessor", name: "oauth2AuthorizationUri", static: false, private: false, access: { has: obj => "oauth2AuthorizationUri" in obj, get: obj => obj.oauth2AuthorizationUri, set: (obj, value) => { obj.oauth2AuthorizationUri = value; } }, metadata: _metadata }, _oauth2AuthorizationUri_initializers, _oauth2AuthorizationUri_extraInitializers);
            __esDecorate(this, null, _oauth2AccessTokenUri_decorators, { kind: "accessor", name: "oauth2AccessTokenUri", static: false, private: false, access: { has: obj => "oauth2AccessTokenUri" in obj, get: obj => obj.oauth2AccessTokenUri, set: (obj, value) => { obj.oauth2AccessTokenUri = value; } }, metadata: _metadata }, _oauth2AccessTokenUri_initializers, _oauth2AccessTokenUri_extraInitializers);
            __esDecorate(this, null, _ignoreContentOnGet_decorators, { kind: "accessor", name: "ignoreContentOnGet", static: false, private: false, access: { has: obj => "ignoreContentOnGet" in obj, get: obj => obj.ignoreContentOnGet, set: (obj, value) => { obj.ignoreContentOnGet = value; } }, metadata: _metadata }, _ignoreContentOnGet_initializers, _ignoreContentOnGet_extraInitializers);
            __esDecorate(this, null, _contentHeadersDialogOpened_decorators, { kind: "accessor", name: "contentHeadersDialogOpened", static: false, private: false, access: { has: obj => "contentHeadersDialogOpened" in obj, get: obj => obj.contentHeadersDialogOpened, set: (obj, value) => { obj.contentHeadersDialogOpened = value; } }, metadata: _metadata }, _contentHeadersDialogOpened_initializers, _contentHeadersDialogOpened_extraInitializers);
            __esDecorate(this, null, _loading_decorators, { kind: "accessor", name: "loading", static: false, private: false, access: { has: obj => "loading" in obj, get: obj => obj.loading, set: (obj, value) => { obj.loading = value; } }, metadata: _metadata }, _loading_initializers, _loading_extraInitializers);
            __esDecorate(this, null, _selectedTab_decorators, { kind: "accessor", name: "selectedTab", static: false, private: false, access: { has: obj => "selectedTab" in obj, get: obj => obj.selectedTab, set: (obj, value) => { obj.selectedTab = value; } }, metadata: _metadata }, _selectedTab_initializers, _selectedTab_extraInitializers);
            __esDecorate(this, null, _ui_decorators, { kind: "accessor", name: "ui", static: false, private: false, access: { has: obj => "ui" in obj, get: obj => obj.ui, set: (obj, value) => { obj.ui = value; } }, metadata: _metadata }, _ui_initializers, _ui_extraInitializers);
            __esDecorate(this, null, _config_decorators, { kind: "accessor", name: "config", static: false, private: false, access: { has: obj => "config" in obj, get: obj => obj.config, set: (obj, value) => { obj.config = value; } }, metadata: _metadata }, _config_initializers, _config_extraInitializers);
            __esDecorate(this, null, _snippets_decorators, { kind: "accessor", name: "snippets", static: false, private: false, access: { has: obj => "snippets" in obj, get: obj => obj.snippets, set: (obj, value) => { obj.snippets = value; } }, metadata: _metadata }, _snippets_initializers, _snippets_extraInitializers);
            if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
        }
        /**
         * A promise set when reading payload from the `request` object.
         * It is resolved after the payload is read anf the `payload` property is set.
         */
        readingPayloadPromise = Promise.resolve();
        /**
         * A promise set when the payload is being written to the `request` object.
         * It is resolved after the `payload` is set on the request as a serializable object.
         */
        writingPayloadPromise = Promise.resolve();
        #readingPayload_accessor_storage = __runInitializers(this, _readingPayload_initializers, false
        /**
         * The base request object.
         */
        );
        /**
         * A flag used to determine when the payload is being read for the synchronous code.
         */
        get readingPayload() { return this.#readingPayload_accessor_storage; }
        set readingPayload(value) { this.#readingPayload_accessor_storage = value; }
        #request_accessor_storage = (__runInitializers(this, _readingPayload_extraInitializers), __runInitializers(this, _request_initializers, new HttpRequest().toJSON()
        /**
         * The request payload.
         * It can be just a string or an object with the payload data depending on the content type.
         */
        ));
        /**
         * The base request object.
         */
        get request() { return this.#request_accessor_storage; }
        set request(value) { this.#request_accessor_storage = value; }
        #payload_accessor_storage = (__runInitializers(this, _request_extraInitializers), __runInitializers(this, _payload_initializers, void 0));
        /**
         * The request payload.
         * It can be just a string or an object with the payload data depending on the content type.
         */
        get payload() { return this.#payload_accessor_storage; }
        set payload(value) { this.#payload_accessor_storage = value; }
        #contentType_accessor_storage = (__runInitializers(this, _payload_extraInitializers), __runInitializers(this, _contentType_initializers, void 0));
        /**
         * The current content type value.
         */
        get contentType() { return this.#contentType_accessor_storage; }
        set contentType(value) { this.#contentType_accessor_storage = value; }
        #authorization_accessor_storage = (__runInitializers(this, _contentType_extraInitializers), __runInitializers(this, _authorization_initializers, void 0));
        get authorization() { return this.#authorization_accessor_storage; }
        set authorization(value) { this.#authorization_accessor_storage = value; }
        #assertions_accessor_storage = (__runInitializers(this, _authorization_extraInitializers), __runInitializers(this, _assertions_initializers, void 0));
        get assertions() { return this.#assertions_accessor_storage; }
        set assertions(value) { this.#assertions_accessor_storage = value; }
        #flows_accessor_storage = (__runInitializers(this, _assertions_extraInitializers), __runInitializers(this, _flows_initializers, void 0));
        get flows() { return this.#flows_accessor_storage; }
        set flows(value) { this.#flows_accessor_storage = value; }
        #oauth2RedirectUri_accessor_storage = (__runInitializers(this, _flows_extraInitializers), __runInitializers(this, _oauth2RedirectUri_initializers, void 0));
        /**
         * Redirect URL for the OAuth2 authorization.
         * If can be also set by dispatching `oauth2-redirect-url-changed`
         * with `value` property on the `detail` object.
         */
        get oauth2RedirectUri() { return this.#oauth2RedirectUri_accessor_storage; }
        set oauth2RedirectUri(value) { this.#oauth2RedirectUri_accessor_storage = value; }
        #readOnly_accessor_storage = (__runInitializers(this, _oauth2RedirectUri_extraInitializers), __runInitializers(this, _readOnly_initializers, false
        /**
         * A value to be passed to the OAuth 2 `authorizationUri` property in case
         * if current configuration has no value.
         * This is to be used as a default value.
         */
        ));
        /**
         * When set the editor is in read only mode.
         */
        get readOnly() { return this.#readOnly_accessor_storage; }
        set readOnly(value) { this.#readOnly_accessor_storage = value; }
        #oauth2AuthorizationUri_accessor_storage = (__runInitializers(this, _readOnly_extraInitializers), __runInitializers(this, _oauth2AuthorizationUri_initializers, void 0));
        /**
         * A value to be passed to the OAuth 2 `authorizationUri` property in case
         * if current configuration has no value.
         * This is to be used as a default value.
         */
        get oauth2AuthorizationUri() { return this.#oauth2AuthorizationUri_accessor_storage; }
        set oauth2AuthorizationUri(value) { this.#oauth2AuthorizationUri_accessor_storage = value; }
        #oauth2AccessTokenUri_accessor_storage = (__runInitializers(this, _oauth2AuthorizationUri_extraInitializers), __runInitializers(this, _oauth2AccessTokenUri_initializers, void 0));
        /**
         * A value to be passed to the OAuth 2 `accessTokenUri` property in case
         * if current configuration has no value.
         * This is to be used as a default value.
         */
        get oauth2AccessTokenUri() { return this.#oauth2AccessTokenUri_accessor_storage; }
        set oauth2AccessTokenUri(value) { this.#oauth2AccessTokenUri_accessor_storage = value; }
        #ignoreContentOnGet_accessor_storage = (__runInitializers(this, _oauth2AccessTokenUri_extraInitializers), __runInitializers(this, _ignoreContentOnGet_initializers, false
        /**
         * When set the `content-` headers warning dialog is rendered.
         */
        ));
        /**
         * When set it ignores all `content-*` headers when the request method is `GET`.
         * When not set or `false` it renders a warning message.
         */
        get ignoreContentOnGet() { return this.#ignoreContentOnGet_accessor_storage; }
        set ignoreContentOnGet(value) { this.#ignoreContentOnGet_accessor_storage = value; }
        #contentHeadersDialogOpened_accessor_storage = (__runInitializers(this, _ignoreContentOnGet_extraInitializers), __runInitializers(this, _contentHeadersDialogOpened_initializers, false
        /**
         * To be set when the request is being transported.
         */
        ));
        /**
         * When set the `content-` headers warning dialog is rendered.
         */
        get contentHeadersDialogOpened() { return this.#contentHeadersDialogOpened_accessor_storage; }
        set contentHeadersDialogOpened(value) { this.#contentHeadersDialogOpened_accessor_storage = value; }
        #loading_accessor_storage = (__runInitializers(this, _contentHeadersDialogOpened_extraInitializers), __runInitializers(this, _loading_initializers, false
        /**
         * An index of currently opened tab.
         * @attribute
         */
        ));
        /**
         * To be set when the request is being transported.
         */
        get loading() { return this.#loading_accessor_storage; }
        set loading(value) { this.#loading_accessor_storage = value; }
        #selectedTab_accessor_storage = (__runInitializers(this, _loading_extraInitializers), __runInitializers(this, _selectedTab_initializers, 'parameters'
        /**
         * Optional instance of the `RequestUiMeta` to store the UI state.
         */
        ));
        /**
         * An index of currently opened tab.
         * @attribute
         */
        get selectedTab() { return this.#selectedTab_accessor_storage; }
        set selectedTab(value) { this.#selectedTab_accessor_storage = value; }
        #ui_accessor_storage = (__runInitializers(this, _selectedTab_extraInitializers), __runInitializers(this, _ui_initializers, void 0));
        /**
         * Optional instance of the `RequestUiMeta` to store the UI state.
         */
        get ui() { return this.#ui_accessor_storage; }
        set ui(value) { this.#ui_accessor_storage = value; }
        #config_accessor_storage = (__runInitializers(this, _ui_extraInitializers), __runInitializers(this, _config_initializers, new RequestConfig().toJSON()
        /**
         * @returns True when the request cannot have the payload on the message.
         */
        ));
        /**
         * HTTP request configuration for the transport.
         */
        get config() { return this.#config_accessor_storage; }
        set config(value) { this.#config_accessor_storage = value; }
        /**
         * @returns True when the request cannot have the payload on the message.
         */
        get isPayload() {
            const { request } = this;
            if (!request || !request.method) {
                return false;
            }
            return !NonPayloadMethods.includes(request.method);
        }
        _awaitingOAuth2authorization = (__runInitializers(this, _config_extraInitializers), false);
        /**
         * This is set by the internal logic. When `ignoreContentOnGet` is set and the headers have `content-` headers
         * a dialog is rendered when trying to send the request. When the user chooses to ignore the warning this
         * flag makes sure that `send()` does not check headers.
         *
         * @todo(pawel): This should be done in the request logic module plugin.
         * Plugins can stop request indefinitely or cancel it.
         */
        ignoreValidationOnGet = false;
        #snippets_accessor_storage = __runInitializers(this, _snippets_initializers, void 0);
        get snippets() { return this.#snippets_accessor_storage; }
        set snippets(value) { this.#snippets_accessor_storage = value; }
        constructor() {
            super();
            __runInitializers(this, _snippets_extraInitializers);
            this.config.enabled = false;
            this.handleInternalSend = this.handleInternalSend.bind(this);
        }
        connectedCallback() {
            super.connectedCallback();
            this.eventsTarget.addEventListener(EventTypes.Http.Request.send, this.handleInternalSend);
        }
        disconnectedCallback() {
            super.disconnectedCallback();
            this.eventsTarget.addEventListener(EventTypes.Http.Request.send, this.handleInternalSend);
        }
        firstUpdated(changedProperties) {
            super.firstUpdated(changedProperties);
            this.computeSnippetsRequest();
        }
        willUpdate(changedProperties) {
            if (changedProperties.has('request')) {
                this.setupContentType();
                this.readingPayloadPromise = this.readPayload();
            }
            if (changedProperties.has('ui') && this.ui) {
                if (this.ui.selectedEditor) {
                    this.selectedTab = this.ui.selectedEditor;
                }
            }
            super.willUpdate(changedProperties);
        }
        setupContentType(request = this.request) {
            if (!request) {
                this.contentType = undefined;
                return;
            }
            if (!request.headersModel) {
                this.contentType = undefined;
                return;
            }
            const item = request.headersModel.find((i) => i.name.toLowerCase() === 'content-type');
            if (!item) {
                this.contentType = undefined;
                return;
            }
            this.contentType = item.value;
            this.setPayloadMimeOption(request, this.contentType);
        }
        async readPayload() {
            const { request } = this;
            if (!request || !request.payload) {
                this.payload = undefined;
                return;
            }
            this.readingPayload = true;
            try {
                this.payload = await PayloadSerializer.deserialize(request.payload);
            }
            catch {
                this.payload = undefined;
            }
            finally {
                this.readingPayload = false;
            }
        }
        /**
         * Validates state of the URL.
         * @return True if the URL has a structure that looks like
         * an URL which means scheme + something
         */
        validateUrl() {
            const { shadowRoot } = this;
            if (!shadowRoot) {
                return true;
            }
            const panel = shadowRoot.querySelector('http-url-input');
            if (!panel) {
                return true;
            }
            return panel.checkValidity();
        }
        /**
         * Checks if current request requires calling `authorize()` on the OAuth2 method.
         *
         * @return This returns `true` only for valid OAuth 2 method that has no access token.
         */
        requiresAuthorization() {
            const { authorization = [] } = this;
            const oauth = authorization.find((method) => method.enabled && method.type === 'oauth 2');
            if (!oauth) {
                return false;
            }
            const authMethod = this.shadowRoot?.querySelector('oauth2-authorization');
            if (!authMethod) {
                return false;
            }
            const cnf = oauth.config;
            if (authMethod.checkValidity() && !cnf.accessToken) {
                return true;
            }
            return false;
        }
        /**
         * Validates headers for `Content-*` entries against current method.
         * @param request The request object
         * @return True if headers are invalid.
         */
        validateContentHeaders(request) {
            const method = request.method || 'get';
            if (method.toLowerCase() !== 'get') {
                return false;
            }
            const any = !!request.headersModel && request.headersModel.some((i) => i.name.toLowerCase().startsWith('content-'));
            if (any) {
                return true;
            }
            return false;
        }
        /**
         * Serializes the current values to the `IHttpRequest`
         */
        async serialize() {
            if (!this.request) {
                const instance = new HttpRequest();
                return instance.toJSON();
            }
            await this.writingPayloadPromise;
            // make sure we copy everything.
            const instance = new HttpRequest(this.request);
            return instance.toJSON();
        }
        /**
         * Dispatches the send request event to the HTTP request engine.
         */
        async send() {
            if (this.loading || !this.request) {
                return;
            }
            if (!this.validateUrl()) {
                return;
            }
            if (this.requiresAuthorization()) {
                const authMethod = this.shadowRoot?.querySelector('oauth2-authorization');
                if (authMethod) {
                    authMethod.authorize();
                    this._awaitingOAuth2authorization = true;
                }
                return;
            }
            const request = await this.serialize();
            // store the URL in the history
            await Events.HttpClient.Model.UrlHistory.add(request.url, this);
            if (!this.ignoreValidationOnGet && this.validateContentHeaders(request)) {
                this.contentHeadersDialogOpened = true;
                return;
            }
            this.ignoreValidationOnGet = false;
            this.notifySend(request);
            CoreEvents.Telemetry.event({
                category: 'Request editor',
                action: 'Send request',
            }, this);
        }
        notifySend(request) {
            this.dispatchEvent(new CustomEvent('send', {
                detail: {
                    request,
                    authorization: this.authorization,
                    config: this.config,
                    assertions: this.assertions,
                },
            }));
        }
        /**
         * If the request does not exist it creates one.
         * @returns The request object.
         */
        getRequest() {
            if (!this.request) {
                const instance = new HttpRequest();
                this.request = instance.toJSON();
            }
            return this.request;
        }
        /**
         * Aborts the request
         */
        abort() {
            this.dispatchEvent(new Event('abort'));
        }
        handleInternalSend(e) {
            e.stopPropagation();
            this.send();
        }
        handleVerbSelection(e) {
            const target = e.detail.item;
            if (!target) {
                return;
            }
            const { verb } = target.dataset;
            if (verb) {
                this.selectVerb(verb);
            }
        }
        /**
         * @param verb The HTTP verb (operation, method)
         */
        selectVerb(verb) {
            const request = this.getRequest();
            request.method = verb;
            this.requestUpdate();
            this.notifyChange();
            this.notifyPropertyChanged('method', verb);
            if (!this.isPayload && this.selectedTab === 'payload') {
                this.selectedTab = 'headers';
            }
            CoreEvents.Telemetry.event({
                category: 'Request editor',
                action: 'Method selected',
                label: verb,
            }, this);
            this.computeSnippetsRequest();
        }
        /**
         * The handler for the URL editor change event
         */
        handlerUrlChange(e) {
            const panel = e.target;
            const { value } = panel;
            this.selectUrl(value);
        }
        /**
         * Commits the change in the URL.
         * @param value The new URL value
         */
        selectUrl(value) {
            const request = this.getRequest();
            request.url = value;
            this.requestUpdate();
            this.notifyChange();
            this.notifyPropertyChanged('url', value);
            this.computeSnippetsRequest();
        }
        handleTabSelect(e) {
            this.selectedTab = e.detail.item.getAttribute('aria-controls');
            if (this.ui) {
                this.ui.selectedEditor = this.selectedTab;
                this.notifyPropertyChanged('ui', this.ui);
            }
            CoreEvents.Telemetry.event({
                category: 'Request editor',
                action: 'Editor switched',
                label: this.selectedTab,
            }, this);
        }
        handleParamsChange(e) {
            const input = e.target;
            this.selectUrl(input.value);
        }
        /**
         * The handler for the headers change event from the headers editor.
         */
        handleHeadersChange(e) {
            e.preventDefault();
            const editor = e.target;
            const { model } = editor;
            this.selectHeaders(model);
            if (!this.ui) {
                return;
            }
            // const { value, source } = node;
            if (!this.ui.headers) {
                this.ui.headers = {};
            }
            // this.ui.headers.source = source;
            this.notifyPropertyChanged('ui', this.ui);
        }
        selectHeaders(model) {
            const request = this.getRequest();
            request.headersModel = model;
            const ct = model.find((h) => h.name.toLowerCase() === 'content-type');
            this.contentType = ct && ct.value;
            this.setPayloadMimeOption(request, this.contentType);
            this.requestUpdate();
            this.notifyChange();
            this.computeSnippetsRequest();
        }
        /**
         * The handler for the body editor change event
         */
        handleBody(e) {
            e.preventDefault();
            const node = e.target;
            const { value, model, selected, contentType } = node;
            this.writingPayloadPromise = this.updatePayload(value, contentType);
            this.computeSnippetsRequest();
            if (!this.ui) {
                return;
            }
            if (!this.ui.body) {
                this.ui.body = {};
            }
            this.ui.body.model = model;
            this.ui.body.selected = selected;
            this.notifyPropertyChanged('ui', this.ui);
        }
        async updatePayload(value, mime) {
            const serialized = await PayloadSerializer.serialize(value);
            const request = this.getRequest();
            request.payload = serialized;
            this.setPayloadMimeOption(request, mime);
            this.payload = value;
            this.requestUpdate();
            this.notifyChange();
            this.notifyPropertyChanged('payload', value);
        }
        /**
         * When `mime` is set it creates the `payloadOptions` property with the mime.
         * @param request The request to set the mime type
         * @param mime the mime type value
         */
        setPayloadMimeOption(request, mime) {
            if (mime) {
                if (!request.payloadOptions) {
                    request.payloadOptions = {};
                }
                request.payloadOptions.mime = mime;
            }
        }
        handleFlows(e) {
            e.preventDefault();
            const node = e.target;
            this.selectFlows(node.model);
        }
        selectFlows(flows) {
            this.flows = flows;
            this.notifyChange();
        }
        handleAssertions(e) {
            e.preventDefault();
            const node = e.target;
            this.selectAssertions(node.model);
        }
        selectAssertions(assertions) {
            this.assertions = assertions;
            this.notifyChange();
        }
        handleConfig(e) {
            const node = e.target;
            this.selectRequestConfig(node.config);
        }
        selectRequestConfig(config) {
            this.config = config;
            this.notifyChange();
        }
        /**
         * Called to notify listeners about a particular property change
         *
         * @param type The property that changed. The resulting event type is
         *             the combination of this value and the `change` suffix.
         * @param value The value of the changed property
         */
        notifyPropertyChanged(type, value) {
            this.dispatchEvent(new CustomEvent(`${type}change`, {
                detail: {
                    value,
                },
            }));
        }
        handleContentWarningClose(e) {
            this.contentHeadersDialogOpened = false;
            if (e.detail.cancelled) {
                return;
            }
            this.ignoreValidationOnGet = true;
            this.send();
        }
        /**
         * When a request change this recomputes the values for code snippets.
         * These are different from the actual values in the request as
         * they contain authorization values applied to it.
         */
        async computeSnippetsRequest() {
            const serialized = await this.serialize();
            const { authorization = [] } = this;
            SecurityProcessor.applyAuthorization(serialized, [...authorization], { immutable: true });
            this.snippets = serialized;
        }
        /**
         * Adds a new authorization object to the request for the given type.
         *
         * @returns The created instance of the authorization.
         */
        addAuthorization(type) {
            const cnf = RequestAuthorization.fromTypedConfig(type, {}, false);
            cnf.enabled = true;
            if (!this.authorization) {
                this.authorization = [];
            }
            this.authorization.push(cnf.toJSON());
            this.notifyPropertyChanged('authorization', this.authorization);
            this.requestUpdate();
            return cnf;
        }
        /**
         * Updates authorization schema on the editor.
         * @param schema The new schema to replace the old one
         * @param isValid Whether the schema is valid.
         */
        updateAuthorization(schema, isValid) {
            const { authorization } = this;
            if (!authorization) {
                return;
            }
            const index = authorization.findIndex((i) => i.type === schema.type);
            if (index === -1) {
                return;
            }
            schema.valid = isValid;
            authorization[index] = schema;
            this.notifyPropertyChanged('authorization', this.authorization);
        }
        /**
         * Removes authorization schema from the editor.
         * @param type The authorization type to remove.
         */
        removeAuthorization(type) {
            const { authorization } = this;
            if (!authorization) {
                return;
            }
            const index = authorization.findIndex((i) => i.type === type);
            if (index === -1) {
                return;
            }
            authorization.splice(index, 1);
            this.notifyPropertyChanged('authorization', this.authorization);
            this.requestUpdate();
        }
        handleAuthAdd(e) {
            const target = e.detail.item;
            if (!target) {
                return;
            }
            const selected = target.dataset.type;
            if (!selected) {
                return;
            }
            this.addAuthorization(selected);
        }
        handleAuthChange(e) {
            const editor = e.target;
            const { authorization } = editor;
            this.updateAuthorization(authorization, editor.checkValidity());
        }
        handleAuthDelete(e) {
            const editor = e.target;
            const { authorization } = editor;
            if (!authorization) {
                return;
            }
            this.removeAuthorization(authorization.type);
        }
        render() {
            return html `
      ${this.renderUrlEditorArea()}
      <div class="surface2 editors">${this.renderTabs()} ${this.renderCurrentEditor()}</div>
      ${this.renderHeadersDialog()}
    `;
        }
        /**
         * @returns The template for the top line with method selector, URL, and options.
         */
        renderUrlEditorArea() {
            return html `
      <div class="url-editor">
        <div class="url-meta">${this.renderUrlMeta()}</div>
        ${this.renderSendButton()}
      </div>
    `;
        }
        renderUrlMeta() {
            return html ` ${this.renderHttpMethodSelector()} ${this.renderUrlEditor()} `;
        }
        /**
         * @returns The template for the HTTP method selector
         */
        renderHttpMethodSelector() {
            const request = this.getRequest();
            const { method = 'GET' } = request;
            return html `
      <ui-dropdown-list
        verticalAlign="top"
        @select="${this.handleVerbSelection}"
        class="verb-dropdown"
        closeOnOutsideClick
      >
        <ui-button color="text" class="button">
          ${method}
          <ui-icon icon="arrowDropDown"></ui-icon>
        </ui-button>
        <ui-list slot="dropdown" role="menu"> ${this.renderHttpVerbOptions()} </ui-list>
      </ui-dropdown-list>
    `;
        }
        /**
         * @returns The templates for each supported HTTP methods
         */
        renderHttpVerbOptions() {
            return HttpMethods.map((method) => html `
        <ui-list-item role="menuitem" image="icon" data-verb="${method}">
          <div slot="start" data-method="${method.toLocaleLowerCase()}" class="http-label"></div>
          ${method}
        </ui-list-item>
      `);
        }
        /**
         * @returns The template for the HTTP URL editor
         */
        renderUrlEditor() {
            const request = this.getRequest();
            const { url = '' } = request;
            const { eventsTarget } = this;
            return html `
      <div class="url-input">
        <http-url-input
          .value="${url}"
          .eventsTarget="${eventsTarget}"
          @change="${this.handlerUrlChange}"
        ></http-url-input>
      </div>
    `;
        }
        /**
         * @returns The template for the "send" or "abort" buttons.
         */
        renderSendButton() {
            if (this.loading) {
                return html `
        <ui-button color="filled" title="Abort the request" class="send-button" @click="${this.abort}">Abort</ui-button>
      `;
            }
            return html `
      <ui-button color="filled" title="Send the request" class="send-button" @click="${this.send}">Send</ui-button>
    `;
        }
        /**
         * @returns The template for the request editor tabs
         */
        renderTabs() {
            const { isPayload, selectedTab } = this;
            //  ui && ui.selectedEditor ||
            const s = selectedTab;
            return html ` <ui-tabs @select="${this.handleTabSelect}" class="editor-tabs">
      <ui-tab .selected="${s === 'parameters'}" aria-controls="parameters" id="parameters-tab">Parameters</ui-tab>
      <ui-tab .selected="${s === 'headers'}" aria-controls="headers" id="headers-tab">Headers</ui-tab>
      <ui-tab ?hidden="${!isPayload}" .selected="${s === 'payload'}" aria-controls="payload" id="payload-tab"
        >Body</ui-tab
      >
      <ui-tab .selected="${s === 'authorization'}" aria-controls="authorization" id="authorization-tab"
        >Authorization</ui-tab
      >
      <ui-tab .selected="${s === 'flows'}" aria-controls="flows" id="flows-tab">Flows</ui-tab>
      <ui-tab .selected="${s === 'assertions'}" aria-controls="assertions" id="assertions-tab">Assertions</ui-tab>
      <ui-tab .selected="${s === 'config'}" aria-controls="config" id="config-tab">Config</ui-tab>
      <ui-tab .selected="${s === 'code-snippets'}" aria-controls="code-snippets" id="code-snippets-tab"
        >Code snippets</ui-tab
      >
    </ui-tabs>`;
        }
        /**
         * @returns The template for the current editor
         */
        renderCurrentEditor() {
            const { selectedTab, isPayload } = this;
            const parametersVisible = selectedTab === 'parameters';
            const headersVisible = selectedTab === 'headers';
            const bodyVisible = isPayload && selectedTab === 'payload';
            const authVisible = selectedTab === 'authorization';
            const codeVisible = selectedTab === 'code-snippets';
            const assertionsVisible = selectedTab === 'assertions';
            const configVisible = selectedTab === 'config';
            const flowsVisible = selectedTab === 'flows';
            return html `
      <div class="panel">
        ${this.renderParameters(parametersVisible)} ${this.renderHeaders(headersVisible)}
        ${this.renderBody(bodyVisible)} ${this.renderAuthorization(authVisible)} ${this.renderHttpFlows(flowsVisible)}
        ${this.renderAssertions(assertionsVisible)} ${this.renderRequestConfig(configVisible)}
        ${this.renderSnippets(codeVisible)}
      </div>
    `;
        }
        renderParameters(visible) {
            const request = this.getRequest();
            const { eventsTarget, readOnly } = this;
            return html `
      <http-url-params-form
        id="parameters"
        aria-describedby="parameters-tab"
        role="tabpanel"
        ?hidden="${!visible}"
        .value="${request.url || ''}"
        .eventsTarget="${eventsTarget}"
        ?readOnly="${readOnly}"
        @change="${this.handleParamsChange}"
      ></http-url-params-form>
    `;
        }
        /**
         * @param visible Whether the panel should not be hidden
         * @returns The template for the headers editor
         */
        renderHeaders(visible) {
            const request = this.getRequest();
            const { eventsTarget, readOnly } = this;
            return html ` <http-headers-form
      id="headers"
      aria-describedby="headers-tab"
      role="tabpanel"
      .eventsTarget="${eventsTarget}"
      .model="${request.headersModel || []}"
      ?hidden="${!visible}"
      @change="${this.handleHeadersChange}"
      ?readonly="${readOnly}"
    ></http-headers-form>`;
        }
        /**
         * @param visible Whether the panel should not be hidden
         * @returns The template for the body editor
         */
        renderBody(visible) {
            const { payload, readOnly, contentType, ui, readingPayload } = this;
            if (readingPayload) {
                return html `<p class="loading-body" id="payload">Preparing the editor...</p>`;
            }
            const body = ui && ui.body;
            const selected = body && body.selected;
            const model = body && body.model;
            return html `
      <http-body-editor
        id="payload"
        aria-describedby="payload-tab"
        role="tabpanel"
        ?hidden="${!visible}"
        ?readOnly="${readOnly}"
        .contentType="${contentType}"
        .model="${model}"
        .value="${(!model && payload) || undefined}"
        selected="${ifDefined(selected)}"
        @change="${this.handleBody}"
        @select="${this.handleBody}"
      ></http-body-editor>
    `;
        }
        /**
         * @param visible Whether the panel should not be hidden
         * @returns The template for the authorization editor
         */
        renderAuthorization(visible) {
            const { authorization } = this;
            return html `
      <section ?hidden="${!visible}" id="authorization" aria-describedby="authorization-tab" role="tabpanel">
        ${this.renderAuthorizationActions(authorization)} ${this.renderAuthorizationList(authorization)}
      </section>
    `;
        }
        renderAuthorizationActions(current = []) {
            const all = ['basic', 'oauth 2', 'open id', 'bearer', 'api key', 'ntlm', 'client certificate'];
            const toRender = all.filter((type) => !current.some((i) => i.type === type));
            return html `
      <ui-dropdown-list verticalAlign="top" @select="${this.handleAuthAdd}" class="auth-dropdown" closeOnOutsideClick>
        <ui-button
          color="tonal"
          title="Add authorization option"
          aria-label="Opens a menu to select authorization option"
          ?disabled="${!toRender.length}"
        >
          <ui-icon icon="arrowDropDown" slot="icon" role="presentation"></ui-icon>
          Add
        </ui-button>
        <ui-list slot="dropdown" role="menu"> ${this.renderAuthorizationOptions(toRender)} </ui-list>
      </ui-dropdown-list>
    `;
        }
        renderAuthorizationOptions(available) {
            return html `
      ${available.map((type) => html ` <ui-list-item role="menuitem" data-type="${type}"> ${authTypeToLabel(type)} </ui-list-item> `)}
    `;
        }
        renderAuthorizationList(authorization = []) {
            if (!Array.isArray(authorization) || !authorization.length) {
                return [this.renderEmptyAuthorization()];
            }
            return authorization.map((item, index) => {
                let content;
                switch (item.type) {
                    case 'basic':
                        content = this.renderBasicAuthorization(item);
                        break;
                    case 'bearer':
                        content = this.renderBearerAuthorization(item);
                        break;
                    case 'ntlm':
                        content = this.renderNtlmAuthorization(item);
                        break;
                    case 'oauth 2':
                        content = this.renderOauthAuthorization(item);
                        break;
                    case 'open id':
                        content = this.renderOidcAuthorization(item);
                        break;
                    case 'client certificate':
                        content = this.renderCCAuthorization(item);
                        break;
                    case 'api key':
                        content = this.renderApiKeyAuthorization(item);
                        break;
                    default:
                }
                if (content) {
                    const isLast = authorization.length === index + 1;
                    return html ` ${content} ${!isLast ? html `<ui-divider></ui-divider>` : ''} `;
                }
                return html ``;
            });
        }
        renderEmptyAuthorization() {
            return html ``;
        }
        renderBasicAuthorization(auth) {
            return html `
      <basic-authorization
        .authorization="${auth}"
        ?readOnly="${this.readOnly}"
        class="auth-panel"
        canToggle
        canDelete
        @change="${this.handleAuthChange}"
        @delete="${this.handleAuthDelete}"
      ></basic-authorization>
    `;
        }
        renderBearerAuthorization(auth) {
            return html `
      <bearer-authorization
        .authorization="${auth}"
        ?readOnly="${this.readOnly}"
        class="auth-panel"
        canToggle
        canDelete
        @change="${this.handleAuthChange}"
        @delete="${this.handleAuthDelete}"
      ></bearer-authorization>
    `;
        }
        renderNtlmAuthorization(auth) {
            return html `
      <ntlm-authorization
        .authorization="${auth}"
        ?readOnly="${this.readOnly}"
        class="auth-panel"
        canToggle
        canDelete
        @change="${this.handleAuthChange}"
        @delete="${this.handleAuthDelete}"
      ></ntlm-authorization>
    `;
        }
        renderOauthAuthorization(auth) {
            return html `
      <oauth2-authorization
        .authorization="${auth}"
        ?readOnly="${this.readOnly}"
        class="auth-panel"
        canToggle
        canDelete
        @change="${this.handleAuthChange}"
        @delete="${this.handleAuthDelete}"
        .defaultRedirectUri="${this.oauth2RedirectUri}"
      ></oauth2-authorization>
    `;
        }
        renderOidcAuthorization(auth) {
            return html `
      <oidc-authorization
        .authorization="${auth}"
        ?readOnly="${this.readOnly}"
        class="auth-panel"
        canToggle
        canDelete
        @change="${this.handleAuthChange}"
        @delete="${this.handleAuthDelete}"
        .defaultRedirectUri="${this.oauth2RedirectUri}"
      ></oidc-authorization>
    `;
        }
        renderCCAuthorization(auth) {
            return html `
      <cc-authorization
        .authorization="${auth}"
        ?readOnly="${this.readOnly}"
        class="auth-panel"
        canToggle
        canDelete
        @change="${this.handleAuthChange}"
        @delete="${this.handleAuthDelete}"
      ></cc-authorization>
    `;
        }
        renderApiKeyAuthorization(auth) {
            return html `
      <apikey-authorization
        .authorization="${auth}"
        ?readOnly="${this.readOnly}"
        class="auth-panel"
        canToggle
        canDelete
        @change="${this.handleAuthChange}"
        @delete="${this.handleAuthDelete}"
      ></apikey-authorization>
    `;
        }
        renderHttpFlows(visible) {
            if (!visible) {
                return '';
            }
            const { flows = [] } = this;
            return html `
      <http-flows
        aria-label="HTTP fLows"
        aria-labelledby="flows-tab"
        id="flows"
        role="tabpanel"
        .model="${flows}"
        @change="${this.handleFlows}"
      ></http-flows>
    `;
        }
        renderAssertions(visible) {
            if (!visible) {
                return '';
            }
            const { assertions = [] } = this;
            return html `
      <http-assertions
        aria-label="Assertions"
        aria-labelledby="assertions-tab"
        id="assertions"
        role="tabpanel"
        .model="${assertions}"
        @change="${this.handleAssertions}"
      ></http-assertions>
    `;
        }
        renderRequestConfig(visible) {
            if (!visible) {
                return nothing;
            }
            const { config } = this;
            return html `
      <http-request-config
        aria-label="Request options"
        aria-labelledby="config-tab"
        id="config"
        role="tabpanel"
        .config="${config}"
        @change="${this.handleConfig}"
      ></http-request-config>
    `;
        }
        /**
         * @param visible Whether the panel should be rendered
         * @returns The template for the Code snippets
         */
        renderSnippets(visible) {
            return html ` <http-snippets
      ?hidden="${!visible}"
      id="code-snippets"
      aria-describedby="code-snippets-tab"
      role="tabpanel"
      .request="${this.snippets}"
    ></http-snippets>`;
        }
        /**
         * @returns The template for the invalid content headers dialog
         */
        renderHeadersDialog() {
            const { contentHeadersDialogOpened } = this;
            return html ` <ui-dialog .open="${contentHeadersDialogOpened}" @close="${this.handleContentWarningClose}">
      <ui-icon slot="icon" icon="warning"></ui-icon>
      <span slot="title">Headers are not valid</span>

      <div>
        <p>
          The <b>GET</b> request should not contain <b>content-*</b> headers. It may cause the server to behave
          unexpectedly.
        </p>
        <p><b>Do you want to continue?</b></p>
      </div>

      <ui-button color="text" value="dismiss" slot="button">Cancel request</ui-button>
      <ui-button color="text" value="confirm" slot="button">Continue</ui-button>
    </ui-dialog>`;
        }
    };
})();
/**
 * An element that renders an HTTP editor.
 *
 * @fires send - A custom event when the user requested to send the request. The detail object is the editor's request.
 * @fires abort - When the user requested to abort the ongoing request.
 * @fires authorizationchange - When authorization data change.
 * @fires uichange - When the UI model change.
 */
export default RequestEditor;
//# sourceMappingURL=RequestEditor.js.map