import { Component, Prop, State, h } from '@stencil/core';
import uniqueId from '../../utils/uniqueId';
import { chevronDown } from '@teliads/icons';
export class TeliaSelect {
  constructor() {
    /** Set select disabled */
    this.disabled = false;
    /** Select element id */
    this.selectId = uniqueId('select');
    /** Additional description id */
    this.additionalId = uniqueId('additional');
    /** Error description id */
    this.errorId = uniqueId('error');
    /** Field needs to be filled, so it can be submitted  */
    this.required = false;
    /** Tracking id is used to identify and count Component usage */
    this.dataTrackingId = 'telia-select';
    /**
     * Select has been blurred at least once.
     */
    this.touched = false;
    /**
     * Real time value of select
     */
    this.selectValue = '';
    /**
     * Error message
     */
    this.errorMessageState = '';
    /**
     * Renders out options property array as option elements if provided
     * Fallbacks to slot element
     */
    this.renderOptionElements = () => {
      const optionsProps = typeof this.options === 'string'
        ? JSON.parse(this.options)
        : this.options;
      if (optionsProps === null || optionsProps === void 0 ? void 0 : optionsProps.length) {
        return optionsProps.map(properties => (h("option", Object.assign({}, properties), properties.label)));
      }
      return h("slot", null);
    };
    /**
     * Renders out options property array as option elements if provided
     * Fallbacks to slot element
     */
    this.renderOptionGroupElements = () => {
      const optionsProps = typeof this.optGroup === 'string'
        ? JSON.parse(this.optGroup)
        : this.optGroup;
      if (optionsProps) {
        return Object.values(optionsProps).map((optGroup) => {
          return (h("optgroup", { label: optGroup.name }, optGroup.options.map(properties => {
            return h("option", Object.assign({}, properties), properties.label);
          })));
        });
      }
      return h("slot", null);
    };
    this.updateSelectedValue = () => {
      var _a;
      // eslint-disable-next-line @stencil/strict-boolean-conditions
      this.selectValue = this.selectElement ? (_a = this.selectElement) === null || _a === void 0 ? void 0 : _a.value : '';
    };
    /**
     * Update error message and keep native input error message in sync.
     */
    this.updateErrorMessage = message => {
      var _a;
      (_a = this.selectElement) === null || _a === void 0 ? void 0 : _a.setCustomValidity(message);
      this.errorMessageState = message;
    };
    this.updateErrorState = (skipTouched = false) => {
      var _a, _b, _c;
      const errorMessageIsSet = !!((_a = this.errorMessageState) === null || _a === void 0 ? void 0 : _a.length);
      const requiredInUse = this.required;
      const generalErrorInUse = !!((_b = this.errorMessage) === null || _b === void 0 ? void 0 : _b.length);
      if (generalErrorInUse) {
        this.updateErrorMessage(this.errorMessage);
        this.touched = true;
        // General error message overrides other errors, so exit here.
        return;
      }
      if (this.required) {
        if (((_c = this.selectElement) === null || _c === void 0 ? void 0 : _c.value.length) === 0 &&
          !!this.requiredErrorMessage) {
          this.updateErrorMessage(this.requiredErrorMessage);
        }
        else if (skipTouched && !!this.requiredErrorMessage) {
          this.updateErrorMessage(this.requiredErrorMessage);
        }
        else {
          // Clear required error
          if (!!this.requiredErrorMessage)
            this.updateErrorMessage('');
        }
      }
      // Clean error message if needed
      if (errorMessageIsSet) {
        if (generalErrorInUse)
          return;
        if (requiredInUse)
          return;
        this.updateErrorMessage('');
      }
    };
  }
  componentWillLoad() {
    this.updateErrorState();
  }
  componentWillUpdate() {
    this.updateErrorState();
  }
  componentDidRender() {
    // This check is for Stencil unit tests. Input element is mocked,
    // but setCustomValidity method is not. It is undefined.
    var _a, _b, _c;
    // eslint-disable-next-line @stencil/strict-boolean-conditions
    if (this.selectElement && ((_a = this.selectElement) === null || _a === void 0 ? void 0 : _a.setCustomValidity)) {
      (_b = this.selectElement) === null || _b === void 0 ? void 0 : _b.setCustomValidity(this.errorMessageState);
    }
    if (this.htmlForm) {
      (_c = this.selectElement) === null || _c === void 0 ? void 0 : _c.setAttribute('form', this.htmlForm);
    }
  }
  render() {
    const showError = this.touched && !!this.errorMessageState.length;
    const showAdditional = !!this.additional;
    const describedBy = showAdditional ? this.additionalId : '';
    return (h("div", { class: {
        'telia-select': true,
        'telia-select--disabled': this.disabled,
      } },
      h("div", { class: "telia-select__main" },
        h("select", { id: this.selectId, ref: ref => (this.selectElement = ref), class: {
            'telia-select__select': true,
            'telia-select__select--touched': this.touched,
          }, "aria-describedby": describedBy, disabled: this.disabled, form: this.htmlForm, required: this.required, onBlur: () => {
            this.touched = true;
            this.updateErrorState();
          }, onChange: () => {
            this.updateSelectedValue();
            this.updateErrorState();
          }, onInvalid: () => {
            this.touched = true;
            this.updateErrorState();
          } }, this.optGroup
          ? this.renderOptionGroupElements()
          : this.renderOptionElements()),
        h("telia-icon", { svg: chevronDown.svg })),
      h("telia-label", { htmlFor: this.selectId },
        this.required && h("span", { "aria-hidden": "true" }, '* '),
        this.label),
      showAdditional && (h("telia-field-assistive-text", { class: "telia-select__additional", id: this.additionalId }, this.additional)),
      showError && (h("telia-field-error", { id: this.errorId, class: "telia-select__error" }, this.errorMessageState)),
      h("telia-vst", { dataTrackingId: this.dataTrackingId })));
  }
  static get is() { return "telia-select"; }
  static get originalStyleUrls() { return {
    "$": ["telia-select.scss"]
  }; }
  static get styleUrls() { return {
    "$": ["telia-select.css"]
  }; }
  static get properties() { return {
    "dataTestid": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Test id set for web component host"
      },
      "attribute": "data-testid",
      "reflect": false
    },
    "disabled": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Set select disabled"
      },
      "attribute": "disabled",
      "reflect": false,
      "defaultValue": "false"
    },
    "htmlForm": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "The form associated with the select component. Provide id of form element."
      },
      "attribute": "html-form",
      "reflect": false
    },
    "selectId": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Select element id"
      },
      "attribute": "select-id",
      "reflect": false,
      "defaultValue": "uniqueId('select')"
    },
    "additional": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "Additional description"
      },
      "attribute": "additional",
      "reflect": false
    },
    "additionalId": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Additional description id"
      },
      "attribute": "additional-id",
      "reflect": false,
      "defaultValue": "uniqueId('additional')"
    },
    "label": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Label for select"
      },
      "attribute": "label",
      "reflect": false
    },
    "name": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Name of the form control when submitted"
      },
      "attribute": "name",
      "reflect": false
    },
    "errorId": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Error description id"
      },
      "attribute": "error-id",
      "reflect": false,
      "defaultValue": "uniqueId('error')"
    },
    "required": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Field needs to be filled, so it can be submitted"
      },
      "attribute": "required",
      "reflect": false,
      "defaultValue": "false"
    },
    "requiredErrorMessage": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "Error message for required"
      },
      "attribute": "required-error-message",
      "reflect": false
    },
    "errorMessage": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "General error message, which overrides other error messages and is shown at initial render"
      },
      "attribute": "error-message",
      "reflect": false
    },
    "options": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string | SelectOptions",
        "resolved": "OptionHTMLAttributes<HTMLOptionElement>[] | string",
        "references": {
          "SelectOptions": {
            "location": "import",
            "path": "../../types/SelectOptions"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Options array with properties provided to them"
      },
      "attribute": "options",
      "reflect": false
    },
    "optGroup": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string | OptGroup[]",
        "resolved": "OptGroup[] | string",
        "references": {
          "OptGroup": {
            "location": "import",
            "path": "../../types/SelectOptions"
          }
        }
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "OptGroup is an Array of OptGroup objects. If both options and optGroup are provided, only optGroup will be rendered.\nIf passed as string, it must parse into array of OptGroup."
      },
      "attribute": "opt-group",
      "reflect": false
    }
  }; }
  static get states() { return {
    "touched": {},
    "selectValue": {},
    "errorMessageState": {}
  }; }
}
