import { h } from '@stencil/core';
import { ElementIDUtils, JSUtils, ObjectUtils } from '@sankhyalabs/core';
import { BreadcrumbItem } from './subcomponents/breadcrumb-item';
export class EzBreadcrumb {
  constructor() {
    this._ellipsesPositionedEnd = false;
    this._renderSecond = false;
    this.INDEX_ITEM_TO_REMOVE = 1; // sempre removemos o segundo item.
    this.CHEVRON_SIZE = 28;
    this.handleShowDropdown = (newState) => {
      this.showDropdown = newState;
    };
    this.items = [];
    this.fillMode = "auto";
    this.maxItems = 4;
    this.positionEllipsis = 1;
    this.visibleItems = undefined;
    this.hiddenItems = [];
    this.showDropdown = false;
    this.collapseConfigPosition = -1;
  }
  watchPropHandler(newValue, oldValue) {
    if (ObjectUtils.objectToString(newValue || []) !== ObjectUtils.objectToString(oldValue || [])) {
      this.loadItems();
    }
    this.fillMode === "auto" && this.handleResize();
  }
  watchPropHiddenItems() {
    if (this.fillMode === 'auto') {
      this.collapseConfigPosition = this.hiddenItems.length > 0 ? 1 : -1;
    }
  }
  componentDidUpdate() {
    this.positionDropdown();
    this.setEvents();
  }
  componentWillLoad() {
    this.loadItems();
  }
  loadItems() {
    this.visibleItems = [...this.items];
    this.hiddenItems = [];
    if (this.fillMode === 'regular') {
      this.configModeRegular();
    }
    else if (this.fillMode === 'auto') {
      this.startResize();
    }
    this.setEvents();
  }
  closeDropdown(evt) {
    const target = evt === null || evt === void 0 ? void 0 : evt.target;
    if (target == undefined) {
      return;
    }
    if (target !== this._element.shadowRoot.querySelector(".ellipses__item")) {
      this.showDropdown = false;
    }
  }
  setEvents() {
    document.removeEventListener("click", this.closeDropdown.bind(this));
    document.addEventListener("click", this.closeDropdown.bind(this));
    document.removeEventListener("scroll", this.positionDropdown.bind(this));
    document.addEventListener("scroll", this.positionDropdown.bind(this));
  }
  componentDidLoad() {
    ElementIDUtils.addIDInfo(this._element);
  }
  componentDidRender() {
    if (this.fillMode === 'auto') {
      this.configResize();
    }
  }
  configResize() {
    if (this._resizeObserver != undefined) {
      this._resizeObserver.unobserve(this._element.parentElement);
    }
    this._resizeObserver = new ResizeObserver(JSUtils.debounce(this.handleResize.bind(this), 200));
    this._resizeObserver.observe(this._element.parentElement);
  }
  handleResize() {
    const ELLIPSIS_SIZE = 39;
    if (!this._renderSecond) {
      this._renderSecond = true;
      return;
    }
    if (this._element.parentElement == undefined) {
      return;
    }
    let { offsetWidth } = this._element.parentElement;
    let sumVisibleItems = 0;
    this.visibleItems.forEach(item => sumVisibleItems += item.width);
    //Se existe o ellipsis, devemos cconsidera-lo no calculo
    const offset = this.collapseConfigPosition > -1 ? ELLIPSIS_SIZE : 0;
    if (offsetWidth < sumVisibleItems + offset) {
      this.handleCollapse(offsetWidth, sumVisibleItems);
    }
    else if (offsetWidth >= sumVisibleItems + offset) {
      this.handleExpand(offsetWidth);
    }
  }
  handleCollapse(containerWidth, itemsWidth) {
    const MIN_VISIBLE_ITEMS = 2;
    if (this.visibleItems.length <= MIN_VISIBLE_ITEMS) {
      return;
    }
    let tmpVisibleItems = [...this.visibleItems];
    let tmpHiddenItems = [...this.hiddenItems];
    let secondItem = tmpVisibleItems[this.INDEX_ITEM_TO_REMOVE];
    let hasChange = false;
    while (tmpVisibleItems.length > MIN_VISIBLE_ITEMS &&
      secondItem != undefined &&
      itemsWidth > containerWidth) {
      hasChange = true;
      tmpVisibleItems = tmpVisibleItems.filter((_, index) => index !== this.INDEX_ITEM_TO_REMOVE);
      tmpHiddenItems = [...tmpHiddenItems, secondItem];
      itemsWidth -= secondItem.width;
      secondItem = tmpVisibleItems[this.INDEX_ITEM_TO_REMOVE];
    }
    if (hasChange) {
      this.visibleItems = tmpVisibleItems;
      this.hiddenItems = tmpHiddenItems;
      this.showDropdown = false;
    }
  }
  handleExpand(containerWidth) {
    if (!this.hiddenItems.length) {
      return;
    }
    let widthFreeZone = Math.abs(this._elBreadcrumbList.offsetWidth - containerWidth);
    let tmpVisibleItems = [...this.visibleItems];
    let tmpHiddenItems = [...this.hiddenItems];
    let lastHiddenElement = tmpHiddenItems[tmpHiddenItems.length - 1];
    let hasChange = false;
    while (lastHiddenElement && widthFreeZone >= lastHiddenElement.width) {
      widthFreeZone -= lastHiddenElement.width;
      tmpHiddenItems.pop();
      tmpVisibleItems.splice(this.INDEX_ITEM_TO_REMOVE, 0, lastHiddenElement);
      lastHiddenElement = tmpHiddenItems[tmpHiddenItems.length - 1];
      hasChange = true;
    }
    if (hasChange) {
      this.visibleItems = tmpVisibleItems;
      this.hiddenItems = tmpHiddenItems;
      this.showDropdown = false;
    }
  }
  configModeRegular() {
    if (this.visibleItems.length > this.maxItems) {
      const amountsItemsToHide = Math.abs(this.visibleItems.length - this.maxItems);
      if (this.positionEllipsis === 0) {
        const itemsToTransfer = this.visibleItems.slice(0, amountsItemsToHide);
        this.hiddenItems.push(...itemsToTransfer);
        this.visibleItems.splice(0, amountsItemsToHide);
      }
      else if (this.positionEllipsis >= this.maxItems) {
        const itemsToTransfer = this.visibleItems.slice(this.maxItems);
        this.hiddenItems.push(...itemsToTransfer);
        this.visibleItems.splice(this.maxItems);
        this._ellipsesPositionedEnd = true;
      }
      else {
        const removedItems = this.visibleItems.splice(this.positionEllipsis, amountsItemsToHide);
        this.hiddenItems.push(...removedItems);
      }
      this.collapseConfigPosition = this.positionEllipsis;
    }
  }
  positionDropdown() {
    var _a;
    const bounding = (_a = this._element.shadowRoot.querySelector(".ellipses__item")) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
    const elDropdown = this._element.shadowRoot.querySelector(".dropdown-ellipsis");
    if (bounding == undefined || elDropdown == undefined) {
      return;
    }
    elDropdown.style.top = (bounding.y + bounding.height + 5) + "px";
    elDropdown.style.left = bounding.x + "px";
  }
  ;
  async startResize() {
    const areaAvailable = this._element.parentElement.offsetWidth;
    const ELLIPSIS_SIZE = 10;
    const measureItemSize = async (item, index) => {
      item.width = await this.measureSizeHTMLElement(item);
      /*
        Se é o ultimo item, desconsideramos o icone CHEVRON
      */
      if (index === this.visibleItems.length - 1) {
        item.width -= this.CHEVRON_SIZE;
      }
      return item;
    };
    const measuredItems = await Promise.all(this.visibleItems.map(measureItemSize));
    const sizeBreadcrumb = measuredItems.reduce((total, item) => total + item.width, 0);
    if (sizeBreadcrumb > areaAvailable) {
      const tempItemsVisible = [];
      const tempItemsHidden = [...measuredItems];
      const firstItem = tempItemsHidden.shift();
      const lastItem = tempItemsHidden.pop();
      lastItem.width += ELLIPSIS_SIZE;
      tempItemsVisible.push(firstItem, lastItem);
      let sizeTempItemsHiddenResult = tempItemsVisible.reduce((total, item) => total + item.width, 0);
      let newAreaAvailable = Math.abs(sizeTempItemsHiddenResult - areaAvailable);
      tempItemsHidden.reverse().forEach((item) => {
        if (item.width < newAreaAvailable) {
          const firstItemForListHidden = tempItemsHidden.shift();
          tempItemsVisible.splice(1, 0, firstItemForListHidden);
          sizeTempItemsHiddenResult = tempItemsVisible.reduce((total, item) => total + item.width, 0);
          newAreaAvailable = Math.abs(sizeTempItemsHiddenResult - areaAvailable);
        }
      });
      this.visibleItems = [...tempItemsVisible];
      this.hiddenItems = [...tempItemsHidden.reverse()];
    }
  }
  measureSizeHTMLElement(item) {
    return new Promise((resolve) => {
      const ICON_SIZE = 19;
      this.waitFontLoad().then(() => {
        if (this._textMesurement === undefined) {
          this._textMesurement = this._element.shadowRoot.ownerDocument.createElement("canvas");
        }
        const context = this._textMesurement.getContext("2d");
        context.font = "14px Roboto, Algerian";
        resolve((item.iconName ? ICON_SIZE : 0) + this.CHEVRON_SIZE + context.measureText(item.label).width);
      });
    });
  }
  waitFontLoad() {
    return new Promise((resolve) => {
      document.fonts.load("14px Roboto").then(() => resolve(), resolve());
    });
  }
  getItemContent() {
    return (h("nav", { class: "breadcrumb" }, h("ol", { class: "breadcrumb__list", ref: elem => this._elBreadcrumbList = elem }, h(BreadcrumbItem, { items: this.visibleItems, selectedItem: this.selectedItem, itemsHidden: this.hiddenItems, showDropdown: this.showDropdown, handleShowDropdown: this.handleShowDropdown, collapseConfigPosition: this.collapseConfigPosition, ellipsesPositionedEnd: this._ellipsesPositionedEnd }))));
  }
  render() {
    return this.getItemContent();
  }
  static get is() { return "ez-breadcrumb"; }
  static get encapsulation() { return "shadow"; }
  static get originalStyleUrls() {
    return {
      "$": ["ez-breadcrumb.css"]
    };
  }
  static get styleUrls() {
    return {
      "$": ["ez-breadcrumb.css"]
    };
  }
  static get properties() {
    return {
      "items": {
        "type": "unknown",
        "mutable": true,
        "complexType": {
          "original": "Array<IBreadcrumbItem>",
          "resolved": "IBreadcrumbItem[]",
          "references": {
            "Array": {
              "location": "global"
            },
            "IBreadcrumbItem": {
              "location": "local"
            }
          }
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Lista de itens do breadcrumb."
        },
        "defaultValue": "[]"
      },
      "fillMode": {
        "type": "string",
        "mutable": true,
        "complexType": {
          "original": "\"auto\" | \"regular\"",
          "resolved": "\"auto\" | \"regular\"",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Define o modo de uso do Breadcrumb."
        },
        "attribute": "fill-mode",
        "reflect": false,
        "defaultValue": "\"auto\""
      },
      "maxItems": {
        "type": "number",
        "mutable": true,
        "complexType": {
          "original": "number",
          "resolved": "number",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Define o limite m\u00E1ximo de itens a serem renderizados."
        },
        "attribute": "max-items",
        "reflect": false,
        "defaultValue": "4"
      },
      "positionEllipsis": {
        "type": "number",
        "mutable": true,
        "complexType": {
          "original": "number",
          "resolved": "number",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Define a posi\u00E7\u00E3o do Ellipsis nos itens vis\u00EDveis do Breadcrumb."
        },
        "attribute": "position-ellipsis",
        "reflect": false,
        "defaultValue": "1"
      }
    };
  }
  static get states() {
    return {
      "visibleItems": {},
      "hiddenItems": {},
      "showDropdown": {},
      "collapseConfigPosition": {}
    };
  }
  static get events() {
    return [{
        "method": "selectedItem",
        "name": "selectedItem",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "docs": {
          "tags": [],
          "text": "Emitido quando um item do breadcrumb \u00E9 selecionado."
        },
        "complexType": {
          "original": "IBreadcrumbItem",
          "resolved": "IBreadcrumbItem",
          "references": {
            "IBreadcrumbItem": {
              "location": "local"
            }
          }
        }
      }];
  }
  static get elementRef() { return "_element"; }
  static get watchers() {
    return [{
        "propName": "items",
        "methodName": "watchPropHandler"
      }, {
        "propName": "hiddenItems",
        "methodName": "watchPropHiddenItems"
      }];
  }
}
