import { __esDecorate, __runInitializers } from "tslib";
/**
@license
Copyright 2020 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 } from 'lit/decorators.js';
import { live } from 'lit/directives/live.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { Property } from '@api-client/core/models/Property.js';
import { decodeUrlEncoded, encodeUrlEncoded, createViewModel, formArrayToString } from './UrlEncodeUtils.js';
import ApiElement from '../ApiElement.js';
import '../../md/icons/ui-icon.js';
import '../../md/icon-button/ui-icon-button.js';
import '../../md/switch/ui-switch.js';
let BodyUrlEncodedEditor = (() => {
    let _classSuper = ApiElement;
    let _instanceExtraInitializers = [];
    let _readOnly_decorators;
    let _readOnly_initializers = [];
    let _readOnly_extraInitializers = [];
    let _disabled_decorators;
    let _disabled_initializers = [];
    let _disabled_extraInitializers = [];
    let _autoEncode_decorators;
    let _autoEncode_initializers = [];
    let _autoEncode_extraInitializers = [];
    let _allowFormInfo_decorators;
    let _allowFormInfo_initializers = [];
    let _allowFormInfo_extraInitializers = [];
    let _set_value_decorators;
    return class BodyUrlEncodedEditor extends _classSuper {
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            _readOnly_decorators = [property({ type: Boolean, reflect: true })];
            _disabled_decorators = [property({ type: Boolean, reflect: true })];
            _autoEncode_decorators = [property({ type: Boolean, reflect: true })];
            _allowFormInfo_decorators = [property({ type: Boolean })];
            _set_value_decorators = [property({ type: String })];
            __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, _disabled_decorators, { kind: "accessor", name: "disabled", static: false, private: false, access: { has: obj => "disabled" in obj, get: obj => obj.disabled, set: (obj, value) => { obj.disabled = value; } }, metadata: _metadata }, _disabled_initializers, _disabled_extraInitializers);
            __esDecorate(this, null, _autoEncode_decorators, { kind: "accessor", name: "autoEncode", static: false, private: false, access: { has: obj => "autoEncode" in obj, get: obj => obj.autoEncode, set: (obj, value) => { obj.autoEncode = value; } }, metadata: _metadata }, _autoEncode_initializers, _autoEncode_extraInitializers);
            __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);
            __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);
            if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
        }
        #readOnly_accessor_storage = (__runInitializers(this, _instanceExtraInitializers), __runInitializers(this, _readOnly_initializers, false
        /**
         * When set all controls are disabled in the form
         * @attribute
         */
        ));
        /**
         * When set the editor is in read only mode.
         * @attribute
         */
        get readOnly() { return this.#readOnly_accessor_storage; }
        set readOnly(value) { this.#readOnly_accessor_storage = value; }
        #disabled_accessor_storage = (__runInitializers(this, _readOnly_extraInitializers), __runInitializers(this, _disabled_initializers, false
        /**
         * When set it automatically encodes and decodes values.
         * @attribute
         */
        ));
        /**
         * When set all controls are disabled in the form
         * @attribute
         */
        get disabled() { return this.#disabled_accessor_storage; }
        set disabled(value) { this.#disabled_accessor_storage = value; }
        #autoEncode_accessor_storage = (__runInitializers(this, _disabled_extraInitializers), __runInitializers(this, _autoEncode_initializers, false
        /**
         * @attribute
         */
        ));
        /**
         * When set it automatically encodes and decodes values.
         * @attribute
         */
        get autoEncode() { return this.#autoEncode_accessor_storage; }
        set autoEncode(value) { this.#autoEncode_accessor_storage = value; }
        #allowFormInfo_accessor_storage = (__runInitializers(this, _autoEncode_extraInitializers), __runInitializers(this, _allowFormInfo_initializers, void 0));
        /**
         * @attribute
         */
        get allowFormInfo() { return this.#allowFormInfo_accessor_storage; }
        set allowFormInfo(value) { this.#allowFormInfo_accessor_storage = value; }
        valueInternal = (__runInitializers(this, _allowFormInfo_extraInitializers), '');
        /**
         * The HTTP body.
         */
        get value() {
            return this.valueInternal;
        }
        set value(value) {
            const old = this.valueInternal;
            if (old === value) {
                return;
            }
            this.valueInternal = value || '';
            this.setupModel(value || '');
        }
        modelInternal = [];
        /**
         * Computed data model for the view.
         * Don't set both `value` and `model`. If the model exists then
         * set only it or otherwise the `value` setter override the model.
         */
        get model() {
            return this.modelInternal;
        }
        set model(value) {
            const old = this.modelInternal;
            if (old === value) {
                return;
            }
            if (Array.isArray(value)) {
                this.modelInternal = value;
            }
            else {
                this.modelInternal = [];
            }
            this.valueInternal = this.modelToValue();
            this.requestUpdate();
        }
        update(cp) {
            if (cp.has('autoEncode')) {
                this.updateValue();
            }
            super.update(cp);
        }
        /**
         * Removes all parameters.
         */
        clear() {
            this.model = [];
            this.updateValue();
            this.requestUpdate();
        }
        /**
         * Removes a parameter from an index.
         */
        removeProperty(index) {
            const items = this.model;
            items.splice(index, 1);
            this.updateValue();
            this.requestUpdate();
        }
        /**
         * Toggles enabled state of a parameter.
         */
        toggleProperty(index, enabled) {
            const items = this.model;
            const item = items[index];
            item.enabled = enabled;
            this.updateValue();
        }
        /**
         * Updates name/value of a parameter on a specific index.
         */
        updateProperty(index, field, value) {
            const item = this.model[index];
            const old = item[field];
            if (old === value) {
                return;
            }
            item[field] = value;
            this.updateValue();
        }
        addParameter(name = '', value = '') {
            if (this.readOnly || this.disabled) {
                return;
            }
            const prop = Property.String(name, value, true);
            const items = this.model;
            items[items.length] = prop.toJSON();
            this.model = items;
            this.requestUpdate();
            this.focusLast();
        }
        updateValue() {
            if (this.readOnly) {
                return;
            }
            this.valueInternal = this.modelToValue();
            this.notifyChange();
        }
        modelToValue() {
            const { model, autoEncode } = this;
            if (autoEncode) {
                const encoded = encodeUrlEncoded(model);
                return formArrayToString(encoded);
            }
            return formArrayToString(this.model);
        }
        /**
         * Called when the `value` property change. It generates the view model
         * for the editor.
         */
        setupModel(value) {
            if (!value) {
                this.model = [];
                return;
            }
            const model = createViewModel(value);
            if (this.autoEncode) {
                this.modelInternal = decodeUrlEncoded(model);
            }
            else {
                this.modelInternal = model;
            }
            this.requestUpdate();
        }
        async focusLast() {
            await this.updateComplete;
            const row = this.shadowRoot?.querySelector('.param-row:last-of-type');
            if (!row) {
                return;
            }
            try {
                const node = row.querySelector('.name-input input');
                if (node) {
                    node.focus();
                }
            }
            catch {
                // ...
            }
        }
        /**
         * Encodes current parameters in the model, updated the value, and notifies the change
         */
        encodeParameters() {
            const encoded = encodeUrlEncoded(this.model);
            this.modelInternal = encoded;
            this.valueInternal = formArrayToString(encoded);
            this.notifyChange();
            this.requestUpdate();
        }
        /**
         * Encodes current parameters in the model, updated the value, and notifies the change
         */
        decodeParameters() {
            const decoded = decodeUrlEncoded(this.model);
            this.modelInternal = decoded;
            this.valueInternal = formArrayToString(decoded);
            this.notifyChange();
            this.requestUpdate();
        }
        handleAdd() {
            this.addParameter();
        }
        handleToggle(e) {
            const node = e.currentTarget;
            const index = Number(node.dataset.index);
            if (Number.isNaN(index)) {
                return;
            }
            this.toggleProperty(index, !!node.checked);
        }
        handleRemove(e) {
            const node = e.currentTarget;
            const index = Number(node.dataset.index);
            if (Number.isNaN(index)) {
                return;
            }
            this.removeProperty(index);
        }
        handleNameChange(e) {
            const input = e.target;
            const index = Number(input.dataset.index);
            if (Number.isNaN(index)) {
                return;
            }
            this.updateProperty(index, 'name', input.value);
            input.checkValidity();
        }
        handleValueChange(e) {
            const input = e.target;
            const index = Number(input.dataset.index);
            if (Number.isNaN(index)) {
                return;
            }
            this.updateProperty(index, 'value', input.value);
            input.checkValidity();
        }
        render() {
            const items = this.model;
            if (!Array.isArray(items) || !items.length) {
                return html `${this.renderEmptyMessage()}${this.renderFormInfo()}`;
            }
            return this.renderParams(items);
        }
        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>
    `;
        }
        renderEmptyMessage() {
            return html ` <div class="empty-message">No parameters added</div> `;
        }
        renderParams(items) {
            return html ` ${items.map((item, index) => this.renderParam(item, index))} ${this.renderFormInfo()} `;
        }
        renderParam(item, index) {
            return html `
      <div class="param-row">
        ${this.renderToggleButton(item, index)} ${this.renderNameField(item, index)}
        ${this.renderValueField(item, index)} ${this.renderDeleteParameter(index)}
      </div>
    `;
        }
        renderToggleButton(item, index) {
            return html `
      <ui-switch
        .checked="${!!item.enabled}"
        @change="${this.handleToggle}"
        title="Enable / disable parameter"
        aria-label="Activate to toggle enabled state of this parameter"
        data-index="${index}"
        ?disabled="${this.readOnly}"
      ></ui-switch>
    `;
        }
        renderDeleteParameter(index) {
            return html `
      <ui-icon-button
        title="Removes this parameter"
        aria-label="Deletes this parameter"
        data-index="${index}"
        @click="${this.handleRemove}"
        ?disabled="${this.readOnly}"
      >
        <ui-icon icon="deleteOutline" role="presentation"></ui-icon>
      </ui-icon-button>
    `;
        }
        renderNameField(item, index) {
            const { autoEncode } = this;
            const pattern = !autoEncode ? '\\S*' : undefined;
            return html `
      <div class="input-wrapper name-input">
        <div class="error" role="presentation">Invalid character</div>
        <div class="state"></div>
        <input
          type="text"
          name="name"
          autocomplete="off"
          .value="${live(item.name)}"
          data-index="${index}"
          ?readOnly="${this.readOnly}"
          pattern="${ifDefined(pattern)}"
          aria-label="Parameter name value"
          @change="${this.handleNameChange}"
        />
      </div>
    `;
        }
        renderValueField(item, index) {
            const { autoEncode } = this;
            const pattern = !autoEncode ? '\\S*' : undefined;
            return html `
      <div class="input-wrapper value-input">
        <div class="error" role="presentation">Invalid character</div>
        <div class="state"></div>
        <input
          type="text"
          name="value"
          .value="${live(item.value)}"
          data-index="${index}"
          ?readOnly="${this.readOnly}"
          pattern="${ifDefined(pattern)}"
          aria-label="Parameter value"
          @change="${this.handleValueChange}"
        />
      </div>
    `;
        }
    };
})();
/**
 * A body editor specializing in URL encoded data.
 */
export default BodyUrlEncodedEditor;
//# sourceMappingURL=BodyUrlEncodedEditor.js.map