import { __decorate } from '../../../../tslib/tslib.es6.mjs.js';
import '../../focus/md-focus-ring.js';
import '../../ripple/ripple.js';
import '../../../../@lit/reactive-element/reactive-element.js';
import { html as x, nothing as T } from '../../../../lit-html/lit-html.js';
import { LitElement as s } from '../../../../lit-element/lit-element.js';
import { property as n } from '../../../../@lit/reactive-element/decorators/property.js';
import { query as e } from '../../../../@lit/reactive-element/decorators/query.js';
import { classMap as e$1 } from '../../../../lit-html/directives/class-map.js';
import { requestUpdateOnAriaChange } from '../../internal/aria/delegate.js';
import { isActivationClick, dispatchActivationClick } from '../../internal/events/form-label-activation.js';
import { redispatchEvent } from '../../internal/events/redispatch-event.js';
import { mixinConstraintValidation, createValidator, getValidityAnchor } from '../../labs/behaviors/constraint-validation.js';
import { mixinElementInternals } from '../../labs/behaviors/element-internals.js';
import { mixinFormAssociated, getFormValue, getFormState } from '../../labs/behaviors/form-associated.js';
import { CheckboxValidator } from '../../labs/behaviors/validators/checkbox-validator.js';

/**
 * @license
 * Copyright 2021 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
// Separate variable needed for closure.
const switchBaseClass = mixinConstraintValidation(mixinFormAssociated(mixinElementInternals(s)));
/**
 * @fires input {InputEvent} Fired whenever `selected` changes due to user
 * interaction (bubbles and composed).
 * @fires change {Event} Fired whenever `selected` changes due to user
 * interaction (bubbles).
 */
class Switch extends switchBaseClass {
    constructor() {
        super();
        /**
         * Puts the switch in the selected state and sets the form submission value to
         * the `value` property.
         */
        this.selected = false;
        /**
         * Shows both the selected and deselected icons.
         */
        this.icons = false;
        /**
         * Shows only the selected icon, and not the deselected icon. If `true`,
         * overrides the behavior of the `icons` property.
         */
        this.showOnlySelectedIcon = false;
        /**
         * When true, require the switch to be selected when participating in
         * form submission.
         *
         * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#validation
         */
        this.required = false;
        /**
         * The value associated with this switch on form submission. `null` is
         * submitted when `selected` is `false`.
         */
        this.value = 'on';
        {
            this.addEventListener('click', (event) => {
                if (!isActivationClick(event) || !this.input) {
                    return;
                }
                this.focus();
                dispatchActivationClick(this.input);
            });
        }
    }
    render() {
        return x `
      <div class="switch ${e$1(this.getRenderClasses())}">
        <input
          id="switch"
          class="touch"
          type="checkbox"
          role="switch"
          aria-label=${this.ariaLabel || T}
          ?checked=${this.selected}
          ?disabled=${this.disabled}
          ?required=${this.required}
          @input=${this.handleInput}
          @change=${this.handleChange} />

        <md-focus-ring part="focus-ring" for="switch"></md-focus-ring>
        <span class="track"> ${this.renderHandle()} </span>
      </div>
    `;
    }
    getRenderClasses() {
        return {
            'selected': this.selected,
            'unselected': !this.selected,
            'disabled': this.disabled,
        };
    }
    renderHandle() {
        const classes = {
            'with-icon': this.showOnlySelectedIcon ? this.selected : this.icons,
        };
        return x `
      ${this.renderTouchTarget()}
      <span class="handle-container">
        <md-ripple for="switch" ?disabled="${this.disabled}"></md-ripple>
        <span class="handle ${e$1(classes)}">
          ${this.shouldShowIcons() ? this.renderIcons() : x ``}
        </span>
      </span>
    `;
    }
    renderIcons() {
        return x `
      <div class="icons">
        ${this.renderOnIcon()}
        ${this.showOnlySelectedIcon ? x `` : this.renderOffIcon()}
      </div>
    `;
    }
    /**
     * https://fonts.google.com/icons?selected=Material%20Symbols%20Outlined%3Acheck%3AFILL%400%3Bwght%40500%3BGRAD%400%3Bopsz%4024
     */
    renderOnIcon() {
        return x `
      <slot class="icon icon--on" name="on-icon">
        <svg viewBox="0 0 24 24">
          <path
            d="M9.55 18.2 3.65 12.3 5.275 10.675 9.55 14.95 18.725 5.775 20.35 7.4Z" />
        </svg>
      </slot>
    `;
    }
    /**
     * https://fonts.google.com/icons?selected=Material%20Symbols%20Outlined%3Aclose%3AFILL%400%3Bwght%40500%3BGRAD%400%3Bopsz%4024
     */
    renderOffIcon() {
        return x `
      <slot class="icon icon--off" name="off-icon">
        <svg viewBox="0 0 24 24">
          <path
            d="M6.4 19.2 4.8 17.6 10.4 12 4.8 6.4 6.4 4.8 12 10.4 17.6 4.8 19.2 6.4 13.6 12 19.2 17.6 17.6 19.2 12 13.6Z" />
        </svg>
      </slot>
    `;
    }
    renderTouchTarget() {
        return x `<span class="touch"></span>`;
    }
    shouldShowIcons() {
        return this.icons || this.showOnlySelectedIcon;
    }
    handleInput(event) {
        const target = event.target;
        this.selected = target.checked;
        // <input> 'input' event bubbles and is composed, don't re-dispatch it.
    }
    handleChange(event) {
        // <input> 'change' event is not composed, re-dispatch it.
        redispatchEvent(this, event);
    }
    [getFormValue]() {
        return this.selected ? this.value : null;
    }
    [getFormState]() {
        return String(this.selected);
    }
    formResetCallback() {
        // The selected property does not reflect, so the original attribute set by
        // the user is used to determine the default value.
        this.selected = this.hasAttribute('selected');
    }
    formStateRestoreCallback(state) {
        this.selected = state === 'true';
    }
    [createValidator]() {
        return new CheckboxValidator(() => ({
            checked: this.selected,
            required: this.required,
        }));
    }
    [getValidityAnchor]() {
        return this.input;
    }
}
(() => {
    requestUpdateOnAriaChange(Switch);
})();
/** @nocollapse */
Switch.shadowRootOptions = {
    mode: 'open',
    delegatesFocus: true,
};
__decorate([
    n({ type: Boolean })
], Switch.prototype, "selected", void 0);
__decorate([
    n({ type: Boolean })
], Switch.prototype, "icons", void 0);
__decorate([
    n({ type: Boolean, attribute: 'show-only-selected-icon' })
], Switch.prototype, "showOnlySelectedIcon", void 0);
__decorate([
    n({ type: Boolean })
], Switch.prototype, "required", void 0);
__decorate([
    n()
], Switch.prototype, "value", void 0);
__decorate([
    e('input')
], Switch.prototype, "input", void 0);

export { Switch };
