import { FloatingManager } from "@sankhyalabs/core";
import { forceUpdate, h } from "@stencil/core";
import initI18n from "../../utils/i18n";
export class EzCalendar {
  constructor() {
    this._firstRender = true;
    this._hoursLabel = ["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23"];
    this._minutosLabel = ["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59"];
    this.value = new Date();
    this.floating = false;
    this.time = false;
    this.showSeconds = false;
  }
  /**
   * Exibe o ez-calendar em uma posição determinada.
   * É possível determinar o posicionamento através dos parâmetros, no formato css.
   */
  async show(top, left, bottom, right) {
    if (this.floating) {
      this._floatingID = FloatingManager.float(this._box, this._container, {
        isFixed: this.isFixed(),
        autoClose: true,
        top,
        left,
        bottom,
        right
      });
      if (!this.isFixed()) {
        window.requestAnimationFrame(() => {
          this._box.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" });
        });
        this.scroll();
      }
    }
  }
  /**
   * Ajusta o posicionamento vertical do ez-calendar conforme a disponibilidade de espaço.
   */
  async fitVertical(topOffset, bottomOffset) {
    const neededHeight = this._container.getBoundingClientRect().bottom + this._calendarHeight;
    const availableBottom = (window.innerHeight || document.documentElement.clientHeight) > neededHeight;
    if (availableBottom) {
      this.show(topOffset + "px", undefined, "unset");
    }
    else {
      this.show("unset", undefined, bottomOffset + "px");
    }
  }
  /**
   * Ajusta o posicionamento horizontal do ez-calendar conforme a disponibilidade de espaço.
   */
  async fitHorizontal(rightOffset) {
    const neededWidth = this._container.getBoundingClientRect().right + this._calendarWidth;
    const availableRight = (window.innerWidth || document.documentElement.clientWidth) > neededWidth;
    if (!availableRight) {
      this.show(undefined, "unset", undefined, rightOffset + "px");
    }
  }
  /**
   * Oculta o ez-calendar.
   */
  async hide() {
    if (this._floatingID !== undefined) {
      FloatingManager.close(this._floatingID);
      this._floatingID = undefined;
    }
  }
  observeValue() {
    if (this.value) {
      this._currentPosition.setTime(this.value.getTime());
      this._currentPosition.setDate(1);
    }
  }
  scrollListener() {
    if (this.floating && this.isFixed()) {
      this.hide();
    }
  }
  isFixed() {
    return this._hostElem.dataset.isFixed === "true";
  }
  getMonthLabel() {
    return this.i18n(`ez-calendar.month.${this._currentPosition.getMonth()}`) + " " + this._currentPosition.getFullYear();
  }
  isSelectedDate(d) {
    if (this.value) {
      return this.value.getDate() == d.getDate() && this.value.getMonth() == d.getMonth() && this.value.getFullYear() == d.getFullYear();
    }
    return false;
  }
  changeMonth(offset) {
    this._currentPosition.setMonth(this._currentPosition.getMonth() + offset);
    forceUpdate(this);
  }
  selectDate(d) {
    let newDate = d;
    if (this.value && (this.time || this.showSeconds)) {
      newDate.setHours(this.value.getHours());
      newDate.setMinutes(this.value.getMinutes());
      if (this.showSeconds) {
        newDate.setSeconds(this.value.getSeconds());
      }
      else {
        newDate.setSeconds(0);
      }
    }
    this.value = newDate;
    this.ezChange.emit(this.value);
  }
  selectHours(hour) {
    if (!this.value) {
      this.value = new Date();
    }
    this.value = new Date(this.value.getFullYear(), this.value.getMonth(), this.value.getDate(), hour, this.value.getMinutes(), this.value.getSeconds());
    this.ezChange.emit(this.value);
  }
  selectMinutes(minute) {
    if (!this.value) {
      this.value = new Date();
    }
    this.value = new Date(this.value.getFullYear(), this.value.getMonth(), this.value.getDate(), this.value.getHours(), minute, this.value.getSeconds());
    this.ezChange.emit(this.value);
  }
  selectSeconds(second) {
    if (!this.value) {
      this.value = new Date();
    }
    this.value = new Date(this.value.getFullYear(), this.value.getMonth(), this.value.getDate(), this.value.getHours(), this.value.getMinutes(), second);
    this.ezChange.emit(this.value);
  }
  updateScroll(element) {
    if (element) {
      const { scrollHeight, clientHeight, scrollTop } = element;
      const remainingScroll = scrollHeight - clientHeight - Math.ceil(scrollTop);
      if (remainingScroll > 0) {
        element.classList.add("endHidden");
      }
      else {
        element.classList.remove("endHidden");
      }
    }
  }
  async componentWillLoad() {
    this.i18n = await initI18n();
  }
  componentDidRender() {
    if (this.floating && this._firstRender) {
      this._calendarHeight = this._box.clientHeight;
      this._calendarWidth = this._box.clientWidth;
      this._box.remove();
      this._firstRender = false;
    }
    this.updateScroll(this._hoursScroll);
    this.updateScroll(this._minutesScroll);
    this.updateScroll(this._secondsScroll);
  }
  componentDidLoad() {
    this.scroll();
  }
  scroll() {
    if (this.time || this.showSeconds) {
      this._hoursScroll.scrollTop = this._hoursSelect.offsetTop - 64;
      this._minutesScroll.scrollTop = this._minutesSelect.offsetTop - 64;
      this.updateScroll(this._hoursScroll);
      this.updateScroll(this._minutesScroll);
      if (this.showSeconds) {
        this._secondsScroll.scrollTop = this._secondsSelect.offsetTop - 64;
        this.updateScroll(this._secondsScroll);
      }
    }
  }
  render() {
    if (this._currentPosition == null) {
      this._currentPosition = new Date();
      if (this.value) {
        this._currentPosition.setTime(this.value.getTime());
      }
      this._currentPosition.setDate(1);
    }
    const firstDate = new Date();
    firstDate.setTime(this._currentPosition.getTime());
    firstDate.setDate(1 - firstDate.getDay());
    return (h("section", { ref: elem => this._container = elem }, h("div", { ref: elem => this._box = elem, class: "calendar__container" }, h("div", { class: "calendar" }, h("div", { class: "calendar__header" }, h("button", { class: "calendar__btn-previous", onClick: () => this.changeMonth(-1) }), h("label", { class: "calendar__lbl-month" }, this.getMonthLabel()), h("button", { class: "calendar__btn-next", onClick: () => this.changeMonth(1) })), h("div", { class: "calendar__body" }, h("div", { class: "calendar__line" }, [...Array(7).keys()].map(day => h("div", { "data-day": this.i18n(`ez-calendar.weekDay.${day}`), class: "calendar__cell calendar__cell--unselectable" }, this.i18n(`ez-calendar.weekDay.${day}`)))), [0, 7, 14, 21, 28, 35].map(offset => h("div", { class: "calendar__line" }, [0, 1, 2, 3, 4, 5, 6].map(index => {
      const date = new Date();
      date.setTime(firstDate.getTime());
      date.setDate(date.getDate() + offset + index);
      let dataDayMonth = `${date.getMonth() + 1}-${date.getDate()}-${date.getFullYear()}`;
      let classNames = "calendar__cell";
      if (this._currentPosition.getMonth() != date.getMonth()) {
        classNames += " calendar__cell--secondary";
      }
      else if (this.isSelectedDate(date)) {
        classNames += " calendar__cell--selected";
      }
      return h("div", { "data-day-month": dataDayMonth, class: classNames, onClick: () => this.selectDate(date) }, date.getDate());
    })))), h("div", { class: "calendar__footer" }, h("button", { class: "calendar__btn-today", onClick: () => this.selectDate(new Date()) }, this.i18n('ez-calendar.today')))), (this.time || this.showSeconds) &&
      h("div", { class: "calendar-time" }, h("div", { class: "calendar-time__header" }, h("div", null, "H"), h("div", { class: "separatorTime" }, ":"), h("div", null, "M"), this.showSeconds &&
        h("div", { class: "separatorTime" }, ":"), this.showSeconds &&
        h("div", null, "S")), h("div", { class: "calendar__body ", style: { display: 'flex', paddingLeft: '12px', paddingRight: '12px' } }, h("div", { class: "calendar__column", ref: elem => this._hoursScroll = elem, onScroll: () => this.updateScroll(this._hoursScroll) }, this._hoursLabel.map((offset, index) => {
        if (index === this.value.getHours()) {
          return (h("div", { style: { display: 'flex' }, ref: elem => this._hoursSelect = elem }, h("div", { "data-hour": offset, class: "calendar__cell calendar__cell--selected", onClick: () => this.selectHours(index) }, offset), h("div", { class: "separatorTime" }, ":")));
        }
        else {
          return (h("div", { style: { display: 'flex' } }, h("div", { "data-hour": offset, class: "calendar__cell", onClick: () => this.selectHours(index) }, offset), h("div", { class: "separatorTime" }, ":")));
        }
      })), h("div", { class: "calendar__column", ref: elem => this._minutesScroll = elem, onScroll: () => this.updateScroll(this._minutesScroll) }, this._minutosLabel.map((offset, index) => {
        if (index === this.value.getMinutes()) {
          return (h("div", { style: { display: 'flex' }, ref: elem => this._minutesSelect = elem }, h("div", { "data-minute": offset, class: "calendar__cell calendar__cell--selected", onClick: () => this.selectMinutes(index) }, offset), this.showSeconds && h("div", { class: "separatorTime" }, ":")));
        }
        else {
          return (h("div", { style: { display: 'flex' } }, h("div", { "data-minute": offset, class: "calendar__cell", onClick: () => this.selectMinutes(index) }, offset), this.showSeconds && h("div", { class: "separatorTime" }, ":")));
        }
      })), this.showSeconds &&
        h("div", { class: "calendar__column", ref: elem => this._secondsScroll = elem, onScroll: () => this.updateScroll(this._secondsScroll) }, this._minutosLabel.map((offset, index) => {
          if (index === this.value.getSeconds()) {
            return (h("div", { "data-second": offset, class: "calendar__cell calendar__cell--selected", onClick: () => this.selectSeconds(index), ref: elem => this._secondsSelect = elem }, offset));
          }
          else {
            return (h("div", { "data-second": offset, class: "calendar__cell", onClick: () => this.selectSeconds(index) }, offset));
          }
        })))))));
  }
  static get is() { return "ez-calendar"; }
  static get encapsulation() { return "shadow"; }
  static get originalStyleUrls() {
    return {
      "$": ["ez-calendar.css"]
    };
  }
  static get styleUrls() {
    return {
      "$": ["ez-calendar.css"]
    };
  }
  static get properties() {
    return {
      "value": {
        "type": "unknown",
        "mutable": true,
        "complexType": {
          "original": "Date",
          "resolved": "Date",
          "references": {
            "Date": {
              "location": "global"
            }
          }
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Define o valor do calend\u00E1rio."
        },
        "defaultValue": "new Date()"
      },
      "floating": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Define se a exibi\u00E7\u00E3o do ez-calendar ser\u00E1 feita pelos m\u00E9todos `show()` e `hide()`."
        },
        "attribute": "floating",
        "reflect": true,
        "defaultValue": "false"
      },
      "time": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Se true a data considera horas e minutos."
        },
        "attribute": "time",
        "reflect": true,
        "defaultValue": "false"
      },
      "showSeconds": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Se true a data considera segundos. Deve ser usado em conjunto com a propriedade `time`."
        },
        "attribute": "show-seconds",
        "reflect": true,
        "defaultValue": "false"
      }
    };
  }
  static get events() {
    return [{
        "method": "ezChange",
        "name": "ezChange",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "docs": {
          "tags": [],
          "text": "Emitido quando acontece a altera\u00E7\u00E3o de valor do calend\u00E1rio."
        },
        "complexType": {
          "original": "Date",
          "resolved": "Date",
          "references": {
            "Date": {
              "location": "global"
            }
          }
        }
      }];
  }
  static get methods() {
    return {
      "show": {
        "complexType": {
          "signature": "(top?: string, left?: string, bottom?: string, right?: string) => Promise<void>",
          "parameters": [{
              "tags": [],
              "text": ""
            }, {
              "tags": [],
              "text": ""
            }, {
              "tags": [],
              "text": ""
            }, {
              "tags": [],
              "text": ""
            }],
          "references": {
            "Promise": {
              "location": "global"
            }
          },
          "return": "Promise<void>"
        },
        "docs": {
          "text": "Exibe o ez-calendar em uma posi\u00E7\u00E3o determinada.\n\u00C9 poss\u00EDvel determinar o posicionamento atrav\u00E9s dos par\u00E2metros, no formato css.",
          "tags": []
        }
      },
      "fitVertical": {
        "complexType": {
          "signature": "(topOffset: number, bottomOffset: number) => Promise<void>",
          "parameters": [{
              "tags": [],
              "text": ""
            }, {
              "tags": [],
              "text": ""
            }],
          "references": {
            "Promise": {
              "location": "global"
            }
          },
          "return": "Promise<void>"
        },
        "docs": {
          "text": "Ajusta o posicionamento vertical do ez-calendar conforme a disponibilidade de espa\u00E7o.",
          "tags": []
        }
      },
      "fitHorizontal": {
        "complexType": {
          "signature": "(rightOffset: number) => Promise<void>",
          "parameters": [{
              "tags": [],
              "text": ""
            }],
          "references": {
            "Promise": {
              "location": "global"
            }
          },
          "return": "Promise<void>"
        },
        "docs": {
          "text": "Ajusta o posicionamento horizontal do ez-calendar conforme a disponibilidade de espa\u00E7o.",
          "tags": []
        }
      },
      "hide": {
        "complexType": {
          "signature": "() => Promise<void>",
          "parameters": [],
          "references": {
            "Promise": {
              "location": "global"
            }
          },
          "return": "Promise<void>"
        },
        "docs": {
          "text": "Oculta o ez-calendar.",
          "tags": []
        }
      }
    };
  }
  static get elementRef() { return "_hostElem"; }
  static get watchers() {
    return [{
        "propName": "value",
        "methodName": "observeValue"
      }];
  }
  static get listeners() {
    return [{
        "name": "scroll",
        "method": "scrollListener",
        "target": "window",
        "capture": true,
        "passive": true
      }];
  }
}
