import { html, nothing } from 'lit';
import { query, state, property } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { live } from 'lit/directives/live.js';
import { boolean } from '../../internal/boolean.mjs';
import { defaultValue } from '../../internal/default-value.mjs';
import { FlowRdfFormControl } from '../../internal/flow-ui-rdf-element.mjs';
import { FormControlController } from '../../internal/form.mjs';
import { HasSlotController } from '../../internal/slot.mjs';
import { watch } from '../../internal/watch.mjs';
import styles from './checkbox.styles.mjs';

var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __decorateClass = (decorators, target, key, kind) => {
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
  for (var i = decorators.length - 1, decorator; i >= 0; i--)
    if (decorator = decorators[i])
      result = (kind ? decorator(target, key, result) : decorator(result)) || result;
  if (kind && result)
    __defProp(target, key, result);
  return result;
};
class FlowUiCheckbox extends FlowRdfFormControl {
  constructor() {
    super(...arguments);
    this.hasSlotController = new HasSlotController(this, "[default]");
    this.formControlController = new FormControlController(this, {
      value: (control) => control.checked ? control.value || "on" : void 0,
      defaultValue: (control) => control.defaultChecked,
      setValue: (control, checked) => control.checked = checked
    });
    this.hasFocus = false;
    this.label = "";
    this.name = "";
    this.size = "medium";
    this.disabled = false;
    this.checked = false;
    this.indeterminate = false;
    this.defaultChecked = false;
    this.reverse = false;
    this.form = "";
    this.required = false;
  }
  connectedCallback() {
    super.connectedCallback();
    this.checked = boolean(this.checked, true);
    this.indeterminate = boolean(this.indeterminate, true);
    this.disabled = boolean(this.disabled, true);
    this.required = boolean(this.required, true);
    this.reverse = boolean(this.reverse, true);
  }
  /** Gets the validity state object */
  get validity() {
    return this.input.validity;
  }
  /** Gets the validation message */
  get validationMessage() {
    return this.input.validationMessage;
  }
  firstUpdated() {
    this.formControlController.updateValidity();
  }
  handleClick() {
    this.checked = !this.checked;
    this.indeterminate = false;
    this.emit("flow-ui-change");
  }
  handleBlur() {
    this.hasFocus = false;
    this.emit("flow-ui-blur");
  }
  handleInput() {
    this.emit("flow-ui-input");
  }
  handleInvalid(event) {
    this.formControlController.setValidity(false);
    this.formControlController.emitInvalidEvent(event);
  }
  handleFocus() {
    this.hasFocus = true;
    this.emit("flow-ui-focus");
  }
  handleDisabledChange() {
    this.formControlController.setValidity(this.disabled);
  }
  handleStateChange() {
    this.input.checked = this.checked;
    this.input.indeterminate = this.indeterminate;
    this.formControlController.updateValidity();
  }
  /** Simulates a click on the checkbox. */
  click() {
    this.input.click();
  }
  /** Sets focus on the checkbox. */
  focus(options) {
    this.input.focus(options);
  }
  /** Removes focus from the checkbox. */
  blur() {
    this.input.blur();
  }
  /** Checks for validity but does not show a validation message. Returns `true` when valid and `false` when invalid. */
  checkValidity() {
    return this.input.checkValidity();
  }
  /** Gets the associated form, if one exists. */
  getForm() {
    return this.formControlController.getForm();
  }
  /** Checks for validity and shows the browser's validation message if the control is invalid. */
  reportValidity() {
    return this.input.reportValidity();
  }
  /**
   * Sets a custom validation message. The value provided will be shown to the user when the form is submitted. To clear
   * the custom validation message, call this method with an empty string.
   */
  setCustomValidity(message) {
    this.input.setCustomValidity(message);
    this.formControlController.updateValidity();
  }
  render() {
    return html`
      <label
        part="base"
        class=${classMap({
      checkbox: true,
      "checkbox--checked": this.checked,
      "checkbox--disabled": this.disabled,
      "checkbox--focused": this.hasFocus,
      "checkbox--indeterminate": this.indeterminate,
      "checkbox--small": this.size === "small",
      "checkbox--medium": this.size === "medium",
      "checkbox--large": this.size === "large",
      "checkbox--reverse": this.reverse
    })}
      >
        <input
          class="checkbox__input"
          type="checkbox"
          title=${this.label}
          name=${this.name}
          value=${ifDefined(this.value)}
          .indeterminate=${live(this.indeterminate)}
          .checked=${live(this.checked)}
          .disabled=${this.disabled}
          .required=${this.required}
          aria-checked=${this.checked ? "true" : "false"}
          @click=${this.handleClick}
          @input=${this.handleInput}
          @invalid=${this.handleInvalid}
          @blur=${this.handleBlur}
          @focus=${this.handleFocus}
        />

        <span
          part="control${this.checked ? " control--checked" : ""}${this.indeterminate ? " control--indeterminate" : ""}"
          class="checkbox__control"
        >
          ${this.checked ? html`
                <flow-ui-icon
                  part="checked-icon"
                  class="checkbox__checked-icon"
                  library="system"
                  name="check"
                ></flow-ui-icon>
              ` : ""}
          ${!this.checked && this.indeterminate ? html`
                <flow-ui-icon
                  part="indeterminate-icon"
                  class="checkbox__indeterminate-icon"
                  library="system"
                  name="indeterminate"
                ></flow-ui-icon>
              ` : ""}
        </span>

        ${this.hasSlotController.test("[default]") ? html`
              <div part="label" class="checkbox__label">
                <slot></slot>
              </div>
            ` : nothing}
      </label>
    `;
  }
}
FlowUiCheckbox.styles = styles;
__decorateClass([
  query('input[type="checkbox"]')
], FlowUiCheckbox.prototype, "input", 2);
__decorateClass([
  state()
], FlowUiCheckbox.prototype, "hasFocus", 2);
__decorateClass([
  property()
], FlowUiCheckbox.prototype, "label", 2);
__decorateClass([
  property()
], FlowUiCheckbox.prototype, "name", 2);
__decorateClass([
  property()
], FlowUiCheckbox.prototype, "value", 2);
__decorateClass([
  property({ reflect: true })
], FlowUiCheckbox.prototype, "size", 2);
__decorateClass([
  property({ type: Boolean, reflect: true })
], FlowUiCheckbox.prototype, "disabled", 2);
__decorateClass([
  property({ type: Boolean, reflect: true })
], FlowUiCheckbox.prototype, "checked", 2);
__decorateClass([
  property({ type: Boolean, reflect: true })
], FlowUiCheckbox.prototype, "indeterminate", 2);
__decorateClass([
  defaultValue("checked")
], FlowUiCheckbox.prototype, "defaultChecked", 2);
__decorateClass([
  property({ type: Boolean, reflect: true })
], FlowUiCheckbox.prototype, "reverse", 2);
__decorateClass([
  property({ reflect: true })
], FlowUiCheckbox.prototype, "form", 2);
__decorateClass([
  property({ type: Boolean, reflect: true })
], FlowUiCheckbox.prototype, "required", 2);
__decorateClass([
  watch("disabled", { waitUntilFirstUpdate: true })
], FlowUiCheckbox.prototype, "handleDisabledChange", 1);
__decorateClass([
  watch(["checked", "indeterminate"], { waitUntilFirstUpdate: true })
], FlowUiCheckbox.prototype, "handleStateChange", 1);

export { FlowUiCheckbox as default };
