import { h } from '@stencil/core';
import { format } from 'date-fns';
import flatpickr from 'flatpickr';
export class Datepicker {
  constructor() {
    this.label = 'Select date';
    this.enableRange = false;
    this.enableTime = false;
    this.doubleCalendar = false;
    this.showCalendarIcon = true;
    this.inline = false;
    this.format = 'Y-m-d H:i';
    this.value = '';
    /**
     *  Flag to disable button
     */
    this.disabled = false;
    /**
     * The minimum date that a user can start picking from (inclusive).
     */
    this.minDate = null;
    /**
     * The maximum date that a user can pick to (inclusive).
     */
    this.maxDate = null;
    /**
     * use date picker as an icon instead of default input.
     */
    this.useAsIcon = false;
    this.selectedDate = '';
    this.selectedDateTime = '';
    /**
     * Error Message for invalid date
     */
    this.errorMessage = null;
  }
  async componentDidLoad() {
    await this.initFlatpickr();
    this.onValueChanged(this.value);
  }
  /**
   * calculate the time zone offset to add to Date
   * This is necessary because we are trying to keep the externally provided UTC date
   * displayed properly in the user's local date without losing offset hours
   *
   * @param date date string
   * @returns Date
   * @example
   * addTimeZoneOffset('2019-10-20T00:00:00.000Z')
   * // => Sat Apr 20 2019 00:00:00 GMT-0400 (Eastern Daylight Time)
   */
  addTimeZoneOffset(date) {
    const timeZoneOffset = new Date().getTimezoneOffset();
    const parsedDate = Date.parse(date);
    return new Date(parsedDate + timeZoneOffset * 60 * 1000);
  }
  /**
   * calculate the time zone offset to subtract from Date
   * This is necessary because we are trying to keep the internally date
   * returned properly in the UTC date without losing offset hours
   * @param date date string
   * @returns Date
   * @example
   * subtractTimeZoneOffset(Sun Oct 20 2019 23:59:59 GMT-0400 (Eastern Daylight Time))
   * // => Sun Oct 20 2019 19:59:59 GMT-0400 (Eastern Daylight Time)
   */
  subtractTimeZoneOffset(date) {
    const timeZoneOffset = new Date().getTimezoneOffset();
    const parsedDate = Date.parse(date);
    return new Date(parsedDate - timeZoneOffset * 60 * 1000);
  }
  async initFlatpickr() {
    let options = Object.assign({ enableTime: this.enableTime, dateFormat: this.format, altInput: typeof this.displayFormat !== 'undefined', altInputClass: '', altFormat: this.displayFormat, mode: this.enableRange ? 'range' : 'single', showMonths: this.doubleCalendar ? 2 : 1, onChange: (_dates, selectedDate) => {
        const date = new Date(selectedDate);
        this.handleDateChanged(date);
      }, inline: this.inline, minDate: this.addTimeZoneOffset(this.minDate), maxDate: this.addTimeZoneOffset(this.maxDate), disable: [
        () => {
          return this.disabled;
        },
      ] }, (this.enableTime && { enableSeconds: true, time_24hr: true, minTime: '00:00:00', maxTime: '23:59:59' }));
    this.flatpickr = flatpickr(this.el.querySelector('.flatpickr'), options);
  }
  onValueChanged(value) {
    if (value) {
      const date = this.addTimeZoneOffset(value);
      this.errorMessage = this.validateDate(date);
      if (this.flatpickr) {
        this.flatpickr.setDate(date, false, this.format);
      }
    }
    else {
      this.errorMessage = this.validateDate(value);
    }
    this.handleDateChanged(this.addTimeZoneOffset(value));
  }
  /**
   * to trigger setting of the minDate in config
   * @param date
   */
  onMinDateChange(date) {
    if (date && this.flatpickr) {
      this.flatpickr.set('minDate', this.addTimeZoneOffset(this.minDate));
    }
  }
  /**
   * to trigger setting of the maxDate in config
   * @param date
   */
  onMaxDateChange(date) {
    if (date && this.flatpickr) {
      this.flatpickr.set('maxDate', this.addTimeZoneOffset(this.maxDate));
    }
  }
  /**
   * to trigger setting of enableTime on change
   * @param enableTime
   */
  onEnableTime(enableTime) {
    if (this.flatpickr) {
      this.flatpickr.set('enableTime', enableTime);
      const date = this.addTimeZoneOffset(this.value);
      // calling handleDate here because on change of enable-time the value is not displayed in the preferred format: yyyy-MM-dd HH:mm:ss
      this.handleDateChanged(date);
      this.initFlatpickr();
    }
  }
  handleDateChanged(date) {
    this.errorMessage = this.validateDate(date);
    this.selectedDate = !!this.enableTime ? format(date, 'yyyy-MM-dd HH:mm:ss') : format(date, 'yyyy-MM-dd');
    this.valueChanged.emit(this.subtractTimeZoneOffset(date.toString()).toISOString());
  }
  /**
   * to trigger setting of the disable in config
   * @param disable
   */
  onDisableChanged(disabled) {
    if (disabled && this.flatpickr) {
      this.flatpickr.config.disable = [
        () => {
          return this.disabled;
        },
      ];
    }
  }
  validateDate(date) {
    let isDate = date instanceof Date && !isNaN(date.valueOf());
    const errorMessages = {
      required: `${this.label} date is required`,
      range: 'Date must be within date range',
      invalid: `Date is not a valid date (expected format: ${this.enableTime ? 'yyyy-MM-dd HH:mm:ss' : 'yyyy-MM-dd'})`,
    };
    let invalid = false;
    let errorMessage = null;
    if (!date) {
      errorMessage = errorMessages.required;
      invalid = true;
    }
    if (isDate) {
      if (date.getTime() > this.addTimeZoneOffset(this.maxDate).getTime() || date.getTime() < this.addTimeZoneOffset(this.minDate).getTime()) {
        errorMessage = errorMessages.range;
        invalid = true;
      }
    }
    else {
      errorMessage = errorMessages.invalid;
      invalid = true;
    }
    this.isInvalid.emit(invalid);
    return {
      invalid: invalid,
      message: errorMessage,
    };
  }
  render() {
    var _a, _b, _c;
    return (h("div", { class: {
        'disabled': this.disabled,
        'flatpickr': true,
        'btn-date-picker': this.useAsIcon,
      } }, this.useAsIcon ? (h("bs-button", { disabled: this.disabled, variant: "light", title: this.label }, h("bs-icon", { icon: "fas fa-calendar-alt", size: 20 }))) : (h("bs-form-row", null, h("bs-form-group", { class: "px-0" }, h("bs-form-label", null, this.label), h("bs-form-control", { "control-id": `datepicker-${this.label.replace(/ /g, '')}`, as: "input", name: `datepicker-${this.label.replace(/ /g, '')}`, type: "text", value: this.selectedDate, onBsBlur: e => {
        var _a, _b, _c, _d;
        const date = !!this.enableTime ? new Date((_b = (_a = e === null || e === void 0 ? void 0 : e.detail) === null || _a === void 0 ? void 0 : _a.target) === null || _b === void 0 ? void 0 : _b.value) : new Date(`${(_d = (_c = e === null || e === void 0 ? void 0 : e.detail) === null || _c === void 0 ? void 0 : _c.target) === null || _d === void 0 ? void 0 : _d.value} 00:00:00`);
        this.handleDateChanged(date);
      }, isInvalid: (_a = this.errorMessage) === null || _a === void 0 ? void 0 : _a.invalid, class: "pr-2" }), ((_b = this.errorMessage) === null || _b === void 0 ? void 0 : _b.invalid) && h("span", { class: "text-danger" }, (_c = this.errorMessage) === null || _c === void 0 ? void 0 : _c.message))))));
  }
  static get is() { return "gd-date-picker"; }
  static get originalStyleUrls() {
    return {
      "$": ["./gd-date-picker.scss"]
    };
  }
  static get styleUrls() {
    return {
      "$": ["gd-date-picker.css"]
    };
  }
  static get properties() {
    return {
      "label": {
        "type": "string",
        "mutable": false,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": ""
        },
        "attribute": "label",
        "reflect": false,
        "defaultValue": "'Select date'"
      },
      "enableRange": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": ""
        },
        "attribute": "enable-range",
        "reflect": false,
        "defaultValue": "false"
      },
      "enableTime": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": ""
        },
        "attribute": "enable-time",
        "reflect": false,
        "defaultValue": "false"
      },
      "doubleCalendar": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": ""
        },
        "attribute": "double-calendar",
        "reflect": false,
        "defaultValue": "false"
      },
      "showCalendarIcon": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": ""
        },
        "attribute": "show-calendar-icon",
        "reflect": false,
        "defaultValue": "true"
      },
      "inline": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": ""
        },
        "attribute": "inline",
        "reflect": false,
        "defaultValue": "false"
      },
      "format": {
        "type": "string",
        "mutable": false,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": ""
        },
        "attribute": "format",
        "reflect": false,
        "defaultValue": "'Y-m-d H:i'"
      },
      "value": {
        "type": "string",
        "mutable": false,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": ""
        },
        "attribute": "value",
        "reflect": false,
        "defaultValue": "''"
      },
      "displayFormat": {
        "type": "string",
        "mutable": false,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": ""
        },
        "attribute": "display-format",
        "reflect": false
      },
      "disabled": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Flag to disable button"
        },
        "attribute": "disabled",
        "reflect": false,
        "defaultValue": "false"
      },
      "minDate": {
        "type": "string",
        "mutable": false,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "The minimum date that a user can start picking from (inclusive)."
        },
        "attribute": "min-date",
        "reflect": false,
        "defaultValue": "null"
      },
      "maxDate": {
        "type": "string",
        "mutable": false,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "The maximum date that a user can pick to (inclusive)."
        },
        "attribute": "max-date",
        "reflect": false,
        "defaultValue": "null"
      },
      "useAsIcon": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "use date picker as an icon instead of default input."
        },
        "attribute": "use-as-icon",
        "reflect": false,
        "defaultValue": "false"
      }
    };
  }
  static get states() {
    return {
      "selectedDate": {},
      "selectedDateTime": {},
      "errorMessage": {}
    };
  }
  static get events() {
    return [{
        "method": "valueChanged",
        "name": "valueChanged",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "docs": {
          "tags": [],
          "text": ""
        },
        "complexType": {
          "original": "any",
          "resolved": "any",
          "references": {}
        }
      }, {
        "method": "isInvalid",
        "name": "isInvalid",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "docs": {
          "tags": [],
          "text": ""
        },
        "complexType": {
          "original": "any",
          "resolved": "any",
          "references": {}
        }
      }];
  }
  static get elementRef() { return "el"; }
  static get watchers() {
    return [{
        "propName": "value",
        "methodName": "onValueChanged"
      }, {
        "propName": "minDate",
        "methodName": "onMinDateChange"
      }, {
        "propName": "maxDate",
        "methodName": "onMaxDateChange"
      }, {
        "propName": "enableTime",
        "methodName": "onEnableTime"
      }, {
        "propName": "disabled",
        "methodName": "onDisableChanged"
      }];
  }
}
