import { __esDecorate, __runInitializers } from "tslib";
import { property } from 'lit/decorators.js';
import { UiElement } from '../../UiElement.js';
import { isDisabled, setDisabled } from '../../../lib/disabled.js';
let CheckedElement = (() => {
    let _classSuper = UiElement;
    let _instanceExtraInitializers = [];
    let _set_disabled_decorators;
    let _name_decorators;
    let _name_initializers = [];
    let _name_extraInitializers = [];
    let _value_decorators;
    let _value_initializers = [];
    let _value_extraInitializers = [];
    let _checked_decorators;
    let _checked_initializers = [];
    let _checked_extraInitializers = [];
    let _indeterminate_decorators;
    let _indeterminate_initializers = [];
    let _indeterminate_extraInitializers = [];
    let _required_decorators;
    let _required_initializers = [];
    let _required_extraInitializers = [];
    let _invalid_decorators;
    let _invalid_initializers = [];
    let _invalid_extraInitializers = [];
    return class CheckedElement extends _classSuper {
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            _set_disabled_decorators = [property({ reflect: true, type: Boolean })];
            _name_decorators = [property({ type: String })];
            _value_decorators = [property({ type: String })];
            _checked_decorators = [property({ type: Boolean, reflect: true })];
            _indeterminate_decorators = [property({ type: Boolean, reflect: true })];
            _required_decorators = [property({ reflect: true, type: Boolean })];
            _invalid_decorators = [property({ type: Boolean, reflect: true })];
            __esDecorate(this, null, _set_disabled_decorators, { kind: "setter", name: "disabled", static: false, private: false, access: { has: obj => "disabled" in obj, set: (obj, value) => { obj.disabled = value; } }, metadata: _metadata }, null, _instanceExtraInitializers);
            __esDecorate(this, null, _name_decorators, { kind: "accessor", name: "name", static: false, private: false, access: { has: obj => "name" in obj, get: obj => obj.name, set: (obj, value) => { obj.name = value; } }, metadata: _metadata }, _name_initializers, _name_extraInitializers);
            __esDecorate(this, null, _value_decorators, { kind: "accessor", name: "value", static: false, private: false, access: { has: obj => "value" in obj, get: obj => obj.value, set: (obj, value) => { obj.value = value; } }, metadata: _metadata }, _value_initializers, _value_extraInitializers);
            __esDecorate(this, null, _checked_decorators, { kind: "accessor", name: "checked", static: false, private: false, access: { has: obj => "checked" in obj, get: obj => obj.checked, set: (obj, value) => { obj.checked = value; } }, metadata: _metadata }, _checked_initializers, _checked_extraInitializers);
            __esDecorate(this, null, _indeterminate_decorators, { kind: "accessor", name: "indeterminate", static: false, private: false, access: { has: obj => "indeterminate" in obj, get: obj => obj.indeterminate, set: (obj, value) => { obj.indeterminate = value; } }, metadata: _metadata }, _indeterminate_initializers, _indeterminate_extraInitializers);
            __esDecorate(this, null, _required_decorators, { kind: "accessor", name: "required", static: false, private: false, access: { has: obj => "required" in obj, get: obj => obj.required, set: (obj, value) => { obj.required = value; } }, metadata: _metadata }, _required_initializers, _required_extraInitializers);
            __esDecorate(this, null, _invalid_decorators, { kind: "accessor", name: "invalid", static: false, private: false, access: { has: obj => "invalid" in obj, get: obj => obj.invalid, set: (obj, value) => { obj.invalid = value; } }, metadata: _metadata }, _invalid_initializers, _invalid_extraInitializers);
            if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
        }
        #_userInteracted = __runInitializers(this, _instanceExtraInitializers);
        static formAssociated = true;
        #_internals = this.attachInternals();
        get form() {
            return this.#_internals && this.#_internals.form;
        }
        get type() {
            return this.localName;
        }
        get disabled() {
            return isDisabled(this);
        }
        /**
         * When set, the button is a disabled state.
         * @attribute
         */
        set disabled(value) {
            const old = isDisabled(this);
            setDisabled(this, value);
            this.requestUpdate('disabled', old);
            this._updateFormValue();
        }
        #name_accessor_storage = __runInitializers(this, _name_initializers, void 0);
        /**
         * The name of the form control, submitted as a pair with the control's value as part of the form data.
         * @attribute
         */
        get name() { return this.#name_accessor_storage; }
        set name(value) { this.#name_accessor_storage = value; }
        #value_accessor_storage = (__runInitializers(this, _name_extraInitializers), __runInitializers(this, _value_initializers, void 0));
        /**
         * When a form is submitted, only checkboxes which are currently checked are submitted to the server,
         * and the reported value is the `value` of the value attribute.
         * If the `value` is not otherwise specified, it is the string `on` by default.
         * @attribute
         */
        get value() { return this.#value_accessor_storage; }
        set value(value) { this.#value_accessor_storage = value; }
        #checked_accessor_storage = (__runInitializers(this, _value_extraInitializers), __runInitializers(this, _checked_initializers, void 0));
        /**
         * A Boolean attribute indicating whether this checkbox is checked.
         *
         * A checkbox's value is only included in the submitted data
         * if the checkbox is currently `checked`. If it is, then the value
         * of the checkbox's `value` attribute is reported as the input's value.
         * @attribute
         */
        get checked() { return this.#checked_accessor_storage; }
        set checked(value) { this.#checked_accessor_storage = value; }
        #indeterminate_accessor_storage = (__runInitializers(this, _checked_extraInitializers), __runInitializers(this, _indeterminate_initializers, void 0));
        /**
         * In addition to the checked and unchecked states, there is a third state a checkbox can be in: indeterminate.
         * This is a state in which it's impossible to say whether the item is toggled on or off.
         *
         * If you submit a form with an indeterminate checkbox, the same thing happens as
         * if the checkbox were unchecked — no data is submitted to represent the checkbox.
         * @attribute
         */
        get indeterminate() { return this.#indeterminate_accessor_storage; }
        set indeterminate(value) { this.#indeterminate_accessor_storage = value; }
        #required_accessor_storage = (__runInitializers(this, _indeterminate_extraInitializers), __runInitializers(this, _required_initializers, void 0));
        /**
         * Set to true to mark the checked element as required.
         * @attribute
         */
        get required() { return this.#required_accessor_storage; }
        set required(value) { this.#required_accessor_storage = value; }
        #invalid_accessor_storage = (__runInitializers(this, _required_extraInitializers), __runInitializers(this, _invalid_initializers, void 0));
        /**
         * While the element can be easily styled with the `:valid` and `:invalid` pseudo classes
         * it also exposes an attribute to style the element as invalid. This attribute changes
         * when the element validation is performed.
         * @attribute
         */
        get invalid() { return this.#invalid_accessor_storage; }
        set invalid(value) { this.#invalid_accessor_storage = value; }
        _validationError = (__runInitializers(this, _invalid_extraInitializers), 'Please check this box if you want to proceed.');
        constructor() {
            super();
            // The default value for the `<input type="checkbox"/>
            this.value = 'on';
            this.checked = false;
            this.indeterminate = false;
            this.#_userInteracted = false;
            this.actionController.cancelKeyboardEvents = true;
            this.addEventListener('invalid', this._invalidHandler.bind(this));
            this.addEventListener('click', this.handleClick.bind(this));
            this.addEventListener('pointerdown', this.handlePointerDown.bind(this));
            this.addEventListener('pointerup', this.handlePointerUp.bind(this));
            this.addEventListener('pointercancel', this.handlePointerCancel.bind(this));
            this.addEventListener('pointerenter', this.handlePointerEnter.bind(this));
            this.addEventListener('pointerleave', this.handlePointerLeave.bind(this));
            this.addEventListener('contextmenu', this.handleContextMenu.bind(this));
            this.addEventListener('keydown', this.handleKeyDown.bind(this));
            this.addEventListener('keyup', this.handleKeyUp.bind(this));
            this.addEventListener('focus', this.handleFocus.bind(this));
            this.addEventListener('blur', this.handleBlur.bind(this));
        }
        connectedCallback() {
            super.connectedCallback();
            if (!this.hasAttribute('role')) {
                this.setAttribute('role', 'checkbox');
            }
            if (!this.hasAttribute('tabindex') && !this.disabled) {
                this.setAttribute('tabindex', '0');
            }
            this._setChecked(this.checked);
        }
        updated(cp) {
            if (cp.has('required')) {
                const value = cp.get('required');
                if (value) {
                    // this.setAttribute('aria-required', 'true');
                    this.#_internals.ariaRequired = 'true';
                }
                else {
                    // this.removeAttribute('aria-required');
                    this.#_internals.ariaRequired = null;
                }
                this._updateFormValue();
            }
            if (cp.has('indeterminate') || cp.has('value')) {
                this._updateFormValue();
            }
            if (cp.has('checked')) {
                this._setChecked(this.checked);
            }
        }
        /**
         * When form-associated custom elements are supported in the browser it
         * is called when the form has been reset
         */
        formResetCallback() {
            this.checked = false;
            this._postCheckedChange();
        }
        /**
         * When form-associated custom elements are supported in the browser it
         * is called when the form state has been restored
         *
         * @param formState Restored value
         */
        formStateRestoreCallback(formState) {
            if (this.value === formState) {
                this.checked = true;
                this._postCheckedChange();
            }
        }
        handleClick(e) {
            super.handleClick(e);
            this.toggle();
        }
        endPress(config) {
            super.endPress(config);
            const { cancelled, reason } = config;
            if (cancelled) {
                return;
            }
            if (reason === 'enter' || reason === 'space') {
                this.toggle();
            }
        }
        handleFocus() {
            //
        }
        handleBlur() {
            //
        }
        _setChecked(value = false) {
            const { indeterminate } = this;
            const attrValue = indeterminate ? 'mixed' : String(value);
            this.setAttribute('aria-checked', attrValue);
            this.#_internals.ariaChecked = attrValue;
            this._updateFormValue();
        }
        _updateFormValue() {
            const { value = null, checked, indeterminate, disabled, required } = this;
            if (!checked || indeterminate || disabled) {
                this.#_internals.setFormValue(null);
            }
            else {
                this.#_internals.setFormValue(value);
            }
            if (required && !checked) {
                this.#_internals.setValidity({
                    valueMissing: true,
                }, this._validationError);
            }
            else if (this.#_internals.validity.valueMissing) {
                this.#_internals.setValidity({});
            }
        }
        notifyChange() {
            // The <input type="checkbox"/> dispatches both events.
            this.dispatchEvent(new Event('input'));
            super.notifyChange();
        }
        _invalidHandler() {
            if (!this.#_userInteracted) {
                return;
            }
            this.invalid = true;
        }
        toggle() {
            if (this.disabled) {
                return;
            }
            this.#_userInteracted = true;
            this.invalid = false;
            this.checked = !this.checked;
            this._updateFormValue();
            this._postCheckedChange();
        }
        _postCheckedChange() {
            this.notifyChange();
            this.#_internals.checkValidity();
        }
        /**
         * Returns true if the element's value has no validity problems; false otherwise.
         * Fires an invalid event at the element in the latter case.
         */
        checkValidity() {
            this.#_userInteracted = true;
            return this.#_internals.checkValidity();
        }
        /**
         * Returns `true` if internals's target element has no validity problems; otherwise, returns false,
         * fires an invalid event at the element, and (if the event isn't canceled) reports
         * the problem to the user.
         */
        reportValidity() {
            this.#_userInteracted = true;
            return this.#_internals.reportValidity();
        }
    };
})();
/**
 * A base class for UI elements that can be checked (as in a form: checkbox, switch, radio).
 *
 * @fires change - when the checked element changes it's checked state
 * @fires input - when the checked element changes it's checked state
 */
export default CheckedElement;
//# sourceMappingURL=CheckedElement.js.map