import { Component, h, Element, Event, Prop, State, Listen, getAssetPath } from "@stencil/core";
import { convertToPlainString, modifiersToClass, allSiblings } from '../../utils/utils';
export class IbkSearchbar {
  constructor() {
    /** Texto de ayuda dentro del searchbar */
    this.placeholder = 'Buscar';
    /** Define un valor predeterminado para el searchbar */
    this.value = '';
    /** Define si el searchbar muestra un icono de carga mientras se hace la consulta */
    this.loading = false;
    /** Define si el buscador no encontró resultados */
    this.empty = false;
    /** Define si el ícono de la lupa se mostrará a la izquierda o derecha */
    this.iconPosition = 'left';
    /** El buscador mostrará los módulos de la web de Interbank Benefit */
    this.benefit = false;
    /** Si el buscador pertenece a Interbank Benefit y no se encuentran resultados, se mostrará la opción de redirigir a Shopstar */
    this.shopstarRedirect = false;
    /** Almacena el estado del cuadro de resultados, cuando está abierto o cerrado */
    this._open = false;
    /** Estado activo o inactivo del searchbar */
    this._focus = false;
    /** Define cuando los resultados de búsqueda han sido encontrados y estan listos para ser procesados */
    this._readyData = false;
    /** Almacena todos los resultados de la búsqueda en un objeto */
    this._resultData = new Array();
    /** Almacena la información filtrada en base a los criterios de búsqueda */
    this._filteredData = new Array();
    /** Navega entre los resultados al usar las flechas del teclado */
    this.navigate = (keyCode) => {
      let overedIndex = Array.from(this._htmlResults).findIndex((html) => html.getAttribute('over') != undefined);
      if (keyCode == 40) {
        overedIndex++;
        if (overedIndex >= this._htmlResults.length) {
          overedIndex = 0;
        }
      }
      else if (keyCode == 38) {
        overedIndex--;
        if (overedIndex < 0) {
          overedIndex = this._htmlResults.length - 1;
        }
      }
      if (overedIndex >= 0) {
        this._htmlResults[overedIndex].setAttribute('over', '');
        this._htmlResults.forEach((html, index) => {
          if (index != overedIndex) {
            html.removeAttribute('over');
          }
        });
      }
      if (keyCode == 13) {
        const selected = this._htmlResults[overedIndex];
        let result = {};
        if (selected) {
          result = {
            value: selected.getAttribute('value'),
            label: selected.getAttribute('label'),
            text: selected.textContent,
            href: selected.getAttribute('href'),
            hrefTarget: selected.getAttribute('href-target')
          };
        }
        else {
          result = {
            value: 'all',
            label: this.value
          };
        }
        this.onselect.emit(result);
        setTimeout(() => {
          this.host.querySelector('.ibk-searchbar__value').blur();
          this._open = false;
        }, 200);
      }
    };
    /** Escucha el evento click sobre alguno de los resultados */
    this.listenResultClick = () => {
      this._htmlResults.forEach((html) => {
        html.addEventListener('onclick', (e) => this.onselect.emit(e.detail));
      });
    };
    /** Función que se ejecuta al escribir en el searchbar */
    this.search = e => {
      const t = e.target;
      this.value = t.value;
      this._htmlResults = this.host.querySelectorAll('ibk-search-result');
      if (this.value.length <= 2 && this._htmlResults.length > 0) {
        Array.from(this._htmlResults, (result) => result.remove());
      }
      if (this.value.length == 3) {
        this._open = true;
        if (this.value != this._lastSearched) {
          this.onsearch.emit({ value: this.value, benefitModule: this._benefitModule });
          Array.from(this._htmlResults, (result) => result.remove());
          this._lastSearched = this.value;
          this.host.setAttribute('loading', '');
          this.createObjectFromResult();
        }
        else {
          this.updateResults();
        }
      }
      if (this.value.length > 3) {
        this.updateResults();
      }
    };
    this.observerCallback = () => {
      this._htmlResults = this.host.querySelectorAll('ibk-search-result');
      this._htmlResults.forEach((result, index) => {
        const data = {
          index,
          value: result.getAttribute('value'),
          label: result.getAttribute('label'),
          parsedLabel: result.getAttribute('label'),
          href: result.getAttribute('href'),
          hrefTarget: result.getAttribute('href-target')
        };
        this._resultData.push(data);
        if (this._resultData.length == 0) {
          this.empty = true;
        }
        else {
          this.empty = false;
        }
      });
      if (this._htmlResults.length > 0) {
        this.host.removeAttribute('loading');
        this.listenResultClick();
        this.updateResults();
        this._observer.disconnect();
      }
    };
    /** Agrega a un objeto global cada resultado encontrado en base a los 3 primeros caracteres */
    this.createObjectFromResult = () => {
      this._resultData = new Array();
      this._observer = new MutationObserver(this.observerCallback);
      this._observer.observe(this.host, { attributes: true, childList: true });
      this._observer.observe(this.host.querySelector('.ibk-searchbar__results'), { attributes: true, childList: true });
    };
    /** Actualiza el objeto mientras el usuario ingresa más de 3 caracteres */
    this.updateResults = () => {
      this._filteredData = new Array();
      const search = this.value.trim().split(' ');
      const orMatch = [];
      const andMatch = [];
      const exactlyMatch = [];
      this._resultData.forEach((data) => {
        const result = data.label.trim().split(' ');
        let fullMatch = false;
        let match = false;
        let exactly = false;
        let wordsMatch = [];
        if (convertToPlainString(data.label).search(convertToPlainString(this.value)) >= 0) {
          exactly = true;
        }
        search.forEach((src, index) => {
          const plainSearch = convertToPlainString(src);
          let found = false;
          result.forEach((res) => {
            const plainResult = convertToPlainString(res);
            if (plainResult.search(plainSearch) >= 0) {
              found = true;
              match = true;
              const added = wordsMatch.findIndex(w => w.text == res);
              if (added < 0) {
                wordsMatch.push({
                  text: res,
                  start: plainResult.search(plainSearch),
                  end: plainResult.search(plainSearch) + plainSearch.length,
                  match: true
                });
              }
              else {
                wordsMatch[added].match = true;
                wordsMatch[added].start = plainResult.search(plainSearch);
                wordsMatch[added].end = plainResult.search(plainSearch) + plainSearch.length;
              }
            }
            else {
              const added = wordsMatch.find(w => w.text == res);
              if (!added) {
                wordsMatch.push({
                  text: res,
                  start: plainResult.search(plainSearch),
                  end: plainResult.search(plainSearch) + plainSearch.length,
                  match: false
                });
              }
            }
          });
          if (index == 0) {
            if (found) {
              fullMatch = true;
            }
          }
          else {
            if (fullMatch && found) {
              fullMatch = true;
            }
            else {
              fullMatch = false;
            }
          }
        });
        const parsed = [];
        wordsMatch.forEach(word => {
          if (word.match) {
            parsed.push(this.highlightMatch(word.text, word.start, word.end));
          }
          else {
            parsed.push(word.text);
          }
        });
        data.parsedLabel = parsed.join(' ');
        if (exactly) {
          const added = exactlyMatch.find(a => a.index == data.index);
          if (added == undefined) {
            exactlyMatch.push(data);
          }
        }
        else {
          if (fullMatch) {
            const added = andMatch.find(a => a.index == data.index);
            if (added == undefined) {
              andMatch.push(data);
            }
          }
          else if (!fullMatch && match) {
            const added = orMatch.find(a => a.index == data.index);
            if (added == undefined) {
              orMatch.push(data);
            }
          }
        }
      });
      this._filteredData = exactlyMatch.concat(andMatch.concat(orMatch));
      this.renderFilteredResults();
    };
    /** Renderiza los resultados en la vista en base al filtro y ordenamiento */
    this.renderFilteredResults = () => {
      if (this._htmlResults.length >= this._filteredData.length) {
        this._htmlResults.forEach((html, index) => {
          const filtered = this._filteredData[index];
          if (filtered != undefined && index <= 5) {
            html.setAttribute('label', filtered.parsedLabel);
            html.setAttribute('value', filtered.value);
          }
          else {
            html.remove();
          }
        });
      }
      else {
        this._filteredData.forEach((filtered, index) => {
          const html = this._htmlResults[index];
          if (html == undefined && index <= 5) {
            const nodeResult = document.createElement('ibk-search-result');
            nodeResult.setAttribute('label', filtered.parsedLabel);
            nodeResult.setAttribute('value', filtered.value);
            const resultsContainer = this.host.querySelector('.ibk-searchbar__results');
            resultsContainer.appendChild(nodeResult);
          }
          else if (html != undefined) {
            html.setAttribute('label', filtered.parsedLabel);
            html.setAttribute('value', filtered.value);
          }
        });
      }
    };
    /** Resalta la coincidencia de la búsqueda y el resultado */
    this.highlightMatch = (label, startMatch, endMatch) => {
      const isFormated = label.search('ibk-search-result__match');
      if (isFormated < 0) {
        let formated = label.split('');
        formated.splice(startMatch, 0, '<strong class="ibk-search-result__match">');
        formated.splice(endMatch + 1, 0, '</strong>');
        return formated.join('');
      }
      else {
        return label;
      }
    };
    this.clear = () => {
      this.value = '';
      const html = this.host.querySelectorAll('ibk-search-result');
      Array.from(html, (html) => html.remove());
      this.empty = false;
    };
  }
  componentDidLoad() {
    this._benefitModule = this.benefit != undefined && this._benefitModule == undefined ? 1 : this._benefitModule;
  }
  componentWillLoad() {
    this.bodyClick();
  }
  /** Configura la clase del componente basado en estados y modificadores */
  containerClass() {
    return modifiersToClass('ibk-searchbar', [
      `icon-${this.iconPosition}`,
      { focus: this._focus },
      { disabled: this.disabled },
      { open: this._open },
      { boxed: this.boxed }
    ]);
  }
  onSearchbarFocusIn() {
    this._focus = true;
    this.benefit && (this._open = true);
  }
  onSearchbarFocusOut() {
    this._focus = false;
  }
  bodyClick() {
    document.body.addEventListener('click', e => {
      const t = e.target;
      const benefitContainer = t.closest('.ibk-searchbar__benefit');
      const inputContainer = t.closest('.ibk-searchbar__input');
      if (benefitContainer == null && inputContainer == null) {
        this._focus = false;
        this._open = false;
      }
      else {
        this.host.querySelector('.ibk-searchbar__value').focus();
      }
    });
  }
  onNavigate(e) {
    if (this.value.length >= 3 && this._focus) {
      this.navigate(e.keyCode);
    }
  }
  setBenefitModule(e) {
    const t = e.target;
    if (!t.matches('ibk-search-result')) {
      this._benefitModule = parseInt(t.getAttribute('data-code'));
      const primary = t.querySelector('.ibk-button--primary');
      if (primary == null && this.value.length >= 3 && this._benefitModule != 5) {
        this._htmlResults.forEach((html) => html.remove());
        this._resultData = [];
        this._filteredData = [];
        this.host.setAttribute('loading', '');
        this.onsearch.emit({ value: this.value.slice(0, 3), benefitModule: this._benefitModule });
        this.createObjectFromResult();
      }
      allSiblings(t).forEach((sib) => sib.setAttribute('appearance', 'secondary'));
      t.setAttribute('appearance', 'primary');
      this.onbenefitclick.emit(this._benefitModule);
      if (this._benefitModule == 5) {
        setTimeout(() => {
          this.host.querySelector('.ibk-searchbar__value').blur();
          this._focus = false;
          this._open = false;
          this.clear();
        }, 100);
      }
    }
  }
  render() {
    return (h("div", { class: this.containerClass(), style: { width: this.width + 'px' } },
      this.label && h("span", { class: "ibk-searchbar__label", innerHTML: this.label }),
      this.subtitle && h("span", { class: "ibk-searchbar__subtitle", innerHTML: this.subtitle }),
      h("label", { class: "ibk-searchbar__input" },
        this.iconPosition == 'left' && h("i", { class: "ibk-searchbar__icon-search icon-m-search" }),
        h("input", { class: "ibk-searchbar__value", type: "text", onInput: this.search, placeholder: this.placeholder, value: this.value }),
        this.value.length >= 1 && h("i", { class: "ibk-searchbar__icon-clear icon-m-status-error", onClick: this.clear }),
        this.iconPosition == 'right' && h("i", { class: "ibk-searchbar__icon-search icon-m-search" })),
      h("div", { class: "ibk-searchbar__results" },
        this.benefit &&
          h("div", { class: "ibk-searchbar__benefit" },
            h("p", { class: "ibk-searchbar__benefit-label" }, "Buscar en"),
            h("div", { class: "ibk-searchbar__benefit-links" },
              h("ibk-button", { "data-code": "1", appearance: "primary", text: "Productos" }),
              h("ibk-button", { "data-code": "2", appearance: "secondary", text: "Vales y giftcards" }),
              h("ibk-button", { "data-code": "4", appearance: "secondary", text: "Canje en tiendas" }),
              h("ibk-button", { "data-code": "5", appearance: "secondary", text: "Viajes", icon: "icon-xs-arrow-right-2" }))),
        this.loading &&
          h("div", { class: "ibk-searchbar__loading" },
            h("span", { class: "ibk-searchbar__loading-icon" }),
            h("span", { class: "ibk-searchbar__loading-text" }, "Buscando")),
        this.empty && !this.loading &&
          h("div", { class: "ibk-searchbar__empty" },
            h("p", { class: "ibk-searchbar__empty-message" }, "No se encontraron resultados"),
            this.shopstarRedirect &&
              h("div", { class: "ibk-searchbar__shopstar" },
                h("p", { class: "ibk-searchbar__shopstar-text" },
                  "Visita ",
                  h("img", { class: "ibk-searchbar__shopstar-img", src: getAssetPath('../assets/images/logo-shopstar.png'), alt: "Shopstar" }),
                  " para continuar con tu b\u00FAsqueda y canjear tus Millas por productos."),
                h("ibk-button", { class: "ibk-searchbar__shopstar-btn", text: "Ir ahora", href: "https://shopstar.pe/", appearance: "secondary", "href-target": "_blank" }))),
        h("slot", null))));
  }
  static get is() { return "ibk-searchbar"; }
  static get originalStyleUrls() { return {
    "$": ["searchbar.css"]
  }; }
  static get styleUrls() { return {
    "$": ["searchbar.css"]
  }; }
  static get properties() { return {
    "placeholder": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Texto de ayuda dentro del searchbar"
      },
      "attribute": "placeholder",
      "reflect": false,
      "defaultValue": "'Buscar'"
    },
    "label": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Texto de ayuda encima del searchbar"
      },
      "attribute": "label",
      "reflect": false
    },
    "subtitle": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Se incluye el subtitulo entre el label (si existiera) y el searchbar"
      },
      "attribute": "subtitle",
      "reflect": false
    },
    "disabled": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "El searchbar no se podr\u00E1 usar"
      },
      "attribute": "disabled",
      "reflect": false
    },
    "width": {
      "type": "number",
      "mutable": false,
      "complexType": {
        "original": "number",
        "resolved": "number",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Configura un ancho fijo para el componente"
      },
      "attribute": "width",
      "reflect": false
    },
    "value": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Define un valor predeterminado para el searchbar"
      },
      "attribute": "value",
      "reflect": false,
      "defaultValue": "''"
    },
    "loading": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Define si el searchbar muestra un icono de carga mientras se hace la consulta"
      },
      "attribute": "loading",
      "reflect": false,
      "defaultValue": "false"
    },
    "empty": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Define si el buscador no encontr\u00F3 resultados"
      },
      "attribute": "empty",
      "reflect": false,
      "defaultValue": "false"
    },
    "iconPosition": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "'right' | 'left'",
        "resolved": "\"left\" | \"right\"",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Define si el \u00EDcono de la lupa se mostrar\u00E1 a la izquierda o derecha"
      },
      "attribute": "icon-position",
      "reflect": false,
      "defaultValue": "'left'"
    },
    "boxed": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "El buscador mostrar\u00E1 un estilo con caja color verde alrededor"
      },
      "attribute": "boxed",
      "reflect": false
    },
    "benefit": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "El buscador mostrar\u00E1 los m\u00F3dulos de la web de Interbank Benefit"
      },
      "attribute": "benefit",
      "reflect": false,
      "defaultValue": "false"
    },
    "shopstarRedirect": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Si el buscador pertenece a Interbank Benefit y no se encuentran resultados, se mostrar\u00E1 la opci\u00F3n de redirigir a Shopstar"
      },
      "attribute": "shopstar-redirect",
      "reflect": false,
      "defaultValue": "false"
    }
  }; }
  static get states() { return {
    "_open": {},
    "_focus": {},
    "_readyData": {},
    "_htmlResults": {}
  }; }
  static get events() { return [{
      "method": "onsearch",
      "name": "onsearch",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": "Emite un evento cuando el searchbar contenga 3 caracteres para realizar la b\u00FAsqueda"
      },
      "complexType": {
        "original": "any",
        "resolved": "any",
        "references": {}
      }
    }, {
      "method": "onedit",
      "name": "onedit",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": "Emite un evento al escribir"
      },
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      }
    }, {
      "method": "onselect",
      "name": "onselect",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": "Emite un evento cuando se selecciona uno de los resultados, enviando un objeto con los datos del resultado"
      },
      "complexType": {
        "original": "SearchResult",
        "resolved": "SearchResult",
        "references": {
          "SearchResult": {
            "location": "import",
            "path": "../search-result/search-result"
          }
        }
      }
    }, {
      "method": "onbenefitclick",
      "name": "onbenefitclick",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": "Emite un evento cuando se selecciona alguno de los botones de Interbank Benefit, env\u00EDa como dato el id del m\u00F3dulo"
      },
      "complexType": {
        "original": "number",
        "resolved": "number",
        "references": {}
      }
    }]; }
  static get elementRef() { return "host"; }
  static get listeners() { return [{
      "name": "focusin",
      "method": "onSearchbarFocusIn",
      "target": undefined,
      "capture": false,
      "passive": false
    }, {
      "name": "focusout",
      "method": "onSearchbarFocusOut",
      "target": undefined,
      "capture": false,
      "passive": false
    }, {
      "name": "keydown",
      "method": "onNavigate",
      "target": undefined,
      "capture": false,
      "passive": false
    }, {
      "name": "onclick",
      "method": "setBenefitModule",
      "target": undefined,
      "capture": false,
      "passive": false
    }]; }
}
