import { Component, Element, Host, Prop, State, h } from '@stencil/core';
import { HiddenFormInputSlot, connectForm, defaultValidator, disconnectForm, guid, initializeValidators, } from '../../utils';
export class Select {
  constructor() {
    //--------------------------------------------------------------------------
    //
    // Props
    //
    //--------------------------------------------------------------------------
    /** Disables select interaction. */
    this.disabled = false;
    /** Allows setting error state. */
    this.error = false;
    /** Sets required state. */
    this.required = false;
    /** Sets select width to default size or full. */
    this.width = 'default';
    /** Tracks initialization of nativeSelect */
    this.nativeSelectInitialized = false;
    /** Instance validation. */
    this.validator = defaultValidator();
    //--------------------------------------------------------------------------
    //
    // Private Methods
    //
    //--------------------------------------------------------------------------
    this.createOptionElement = (option, selectEl, index) => {
      let newOption;
      if (this.optionLookup[option.getAttribute('value')] && this.optionLookup[option.getAttribute('value')].length > 0) {
        if (option.getAttribute('selected') || option.getAttribute('selected') === '') {
          this.defaultSelectedIndex = index;
        }
        newOption = this.optionLookup[option.getAttribute('value')].shift();
      }
      else {
        newOption = this.host.ownerDocument.createElement('option');
        newOption.innerText = option.innerText;
        newOption.setAttribute('value', option.getAttribute('value'));
        if (option.getAttribute('disabled') || option.getAttribute('disabled') === '') {
          newOption.setAttribute('disabled', option.getAttribute('disabled'));
        }
        if (option.getAttribute('selected') || option.getAttribute('selected') === '') {
          newOption.setAttribute('selected', option.getAttribute('selected'));
          this.defaultSelectedIndex = index;
        }
      }
      selectEl.options[index] = newOption;
      return newOption;
    };
    this.onChange = () => {
      this.value = this.nativeSelect.value;
    };
    this.onFocus = () => { var _a; return (_a = this.nativeSelect) === null || _a === void 0 ? void 0 : _a.focus(); };
    this.optionLookup = {};
    this.renderNativeSelect = () => {
      if (!this.nativeSelectInitialized) {
        this.syncSelectOptions(this.nativeSelect);
      }
      const selectedOption = this.nativeSelect.options[this.nativeSelect.selectedIndex];
      this.nativeSelect.classList[this.nativeSelect.selectedIndex === 0 && this.nativeSelect.value === '' ? 'add' : 'remove']('placeholder');
      this.nativeSelect.classList[selectedOption.getAttribute('disabled') !== null ? 'add' : 'remove']('disabled-selected');
      this.nativeSelectInitialized = true;
    };
    //--------------------------------------------------------------------------
    //
    // Private State
    //
    //--------------------------------------------------------------------------
    /** Hides error/invalid state on initial render. */
    this.isErrorHidden = true;
  }
  syncSelectOptions(el) {
    const existingOptions = [...el.children];
    if (this.placeholder && !(existingOptions[0] && existingOptions[0].value === '')) {
      const placeholderOption = this.host.ownerDocument.createElement('option');
      placeholderOption.innerText = this.placeholder;
      placeholderOption.setAttribute('value', '');
      placeholderOption.setAttribute('disabled', '');
      placeholderOption.setAttribute('selected', '');
      placeholderOption.classList.add('placeholder');
      el.appendChild(placeholderOption);
    }
    if (this.placeholder)
      existingOptions.shift();
    existingOptions.forEach((option) => {
      if (!this.optionLookup[option.value]) {
        this.optionLookup[option.value] = [option];
      }
      else {
        this.optionLookup[option.value].push(option);
      }
    });
    const abdsOptions = this.host.querySelectorAll('abds-select-option');
    const placeholderIndexShift = this.placeholder ? 1 : 0;
    const currentSelectedOption = el.options[el.selectedIndex];
    abdsOptions.forEach((option, index) => {
      const newOption = this.createOptionElement(option, el, placeholderIndexShift + index);
      if (newOption === currentSelectedOption) {
        el.selectedIndex = placeholderIndexShift + index;
      }
    });
    if (el.selectedIndex < 0)
      el.selectedIndex = this.defaultSelectedIndex;
    // Removes obsolete options
    if (el.options.length > abdsOptions.length + placeholderIndexShift) {
      el.options.length = abdsOptions.length + placeholderIndexShift;
    }
  }
  /** Method for select to provide form reset behavior. */
  onFormReset() {
    this.nativeSelect.selectedIndex = this.defaultSelectedIndex;
  }
  //--------------------------------------------------------------------------
  //
  // Lifecycle Methods
  //
  //--------------------------------------------------------------------------
  componentWillLoad() {
    var _a;
    this.selectId = this.host.id || `input-${guid()}`;
    this.linkedLabelText = (_a = document.querySelector(`label[for="${this.host.id}"]`)) === null || _a === void 0 ? void 0 : _a.textContent;
    this.validator = initializeValidators(this);
    this.optionListObserver = new MutationObserver((mutationList) => {
      mutationList = mutationList.filter((mutation) => mutation.target.tagName === 'ABDS-SELECT' && mutation.type === 'childList');
      if (mutationList.length) {
        this.syncSelectOptions(this.nativeSelect);
      }
    });
    this.optionListObserver.observe(this.host, { attributes: true, childList: true });
    console.log('Select componentWillLoad');
  }
  connectedCallback() {
    connectForm(this);
    console.log('Select connectedCallback');
  }
  disconnectedCallback() {
    var _a;
    (_a = this.optionListObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
    disconnectForm(this);
    console.log('Select disconnectedCallback');
  }
  render() {
    const isInvalid = !this.validator.validate(this.nativeSelect) && !this.isErrorHidden;
    let errorText;
    if (isInvalid)
      errorText = this.validator.errorMessage;
    if (this.error)
      errorText = this.errorMessage;
    return (h(Host, { onClick: this.onFocus },
      this.label && (h("abds-label", { required: this.required, tooltip: this.tooltip }, this.label)),
      h("div", { class: { 'select-container': true, invalid: isInvalid || this.error } },
        h("select", { "aria-describedby": this.errorMessage || this.helperText || isInvalid ? this.selectId : undefined, "aria-label": this.label || this.linkedLabelText || undefined, disabled: this.disabled, name: this.name, onChange: this.onChange, ref: (nativeSelect) => {
            this.nativeSelect = nativeSelect;
            this.renderNativeSelect();
          }, required: this.required }),
        h("abds-icon", { icon: "arrow-down-1", size: "md", "stroke-width": "semibold" })),
      (this.errorMessage || this.helperText || isInvalid) && (h("abds-supporting-text", { errorText: errorText, "helper-text": this.helperText, id: this.selectId })),
      h(HiddenFormInputSlot, { component: this, type: "text" })));
  }
  static get is() { return "abds-select"; }
  static get encapsulation() { return "shadow"; }
  static get originalStyleUrls() { return {
    "$": ["select.css"]
  }; }
  static get styleUrls() { return {
    "$": ["select.css"]
  }; }
  static get properties() { return {
    "disabled": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Disables select interaction."
      },
      "attribute": "disabled",
      "reflect": true,
      "defaultValue": "false"
    },
    "error": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Allows setting error state."
      },
      "attribute": "error",
      "reflect": true,
      "defaultValue": "false"
    },
    "errorMessage": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Custom error message."
      },
      "attribute": "error-message",
      "reflect": true
    },
    "helperText": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Text of the information message."
      },
      "attribute": "helper-text",
      "reflect": true
    },
    "label": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Sets label text in embedded abds-label."
      },
      "attribute": "label",
      "reflect": true
    },
    "name": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": true,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Sets name attribute."
      },
      "attribute": "name",
      "reflect": true
    },
    "placeholder": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Optional placeholder text."
      },
      "attribute": "placeholder",
      "reflect": true
    },
    "required": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Sets required state."
      },
      "attribute": "required",
      "reflect": true,
      "defaultValue": "false"
    },
    "requiredMessage": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Specifies a custom error message for required state."
      },
      "attribute": "required-message",
      "reflect": true
    },
    "tooltip": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Sets tooltip text in embedded abds-label."
      },
      "attribute": "tooltip",
      "reflect": true
    },
    "value": {
      "type": "string",
      "mutable": true,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Value to be submitted to form if selected."
      },
      "attribute": "value",
      "reflect": true
    },
    "width": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "'default' | 'full'",
        "resolved": "\"default\" | \"full\"",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Sets select width to default size or full."
      },
      "attribute": "width",
      "reflect": true,
      "defaultValue": "'default'"
    }
  }; }
  static get states() { return {
    "isErrorHidden": {}
  }; }
  static get elementRef() { return "host"; }
}
//# sourceMappingURL=select.js.map