<template>
  <div class="itf-daterange-picker" :class="{ 'with-addon addon-start': prependIcon, 'with-addon addon-end': clearable }">
    <div class="addon" v-if="prependIcon">
      <slot name="addon">
        <itf-icon :name="prependIcon" />
      </slot>
    </div>
    <div class="input-group form-control py-0"
         :class="{ 'disabled': disabled, 'focused': focused, 'is-invalid': isInvalid(), 'is-valid': isSuccess() }"
         ref="group">
      <i-mask-component
        ref="input"
        class="form-control"
        :class="{ 'placeholder-visible': !displayValue || !displayValue[0], 'bg-transparent': disabled }"
        @input="updateValue($event, 0)"
        @focus="onFocus"
        @blur="onBlur($event, 0)"
        :value="displayValue[0]"
        :mask="Date"
        :pattern="dateFormat"
        :blocks="blocks"
        :disabled="disabled"
        :format="format"
        :parse="parse"
        :unmask="false"
        :lazy="!focused"
        :placeholder="placeholder"
      />
      <span v-if="displayValue && displayValue[0]" class="input-group-text" :class="{'hidden': !focused && (value && !value[0])}">-</span>

      <i-mask-component
        v-if="displayValue && displayValue[0]"
        ref="input2"
        class="form-control"
        @input="updateValue($event, 1)"
        @focus="onFocus"
        @blur="onBlur($event, 1)"
        :value="displayValue[1]"
        :mask="Date"
        :pattern="dateFormat"
        :blocks="blocks"
        :format="format"
        :parse="parse"
        :unmask="false"
        :lazy="!focused"
      />
    </div>
    <div style="display: none">
      <div ref="dropdown" class="itf-daterange-picker__dropdown">
        <itf-date-range-picker-inline
          :compare="compare"
          :range="range"
          :value="value"
          :start-view="startView"
          :only-calendar="onlyCalendar"
          :display-format="displayFormat"
          :value-format="valueFormat"
          :min-date="minDate"
          :max-date="maxDate"
          :days-list="daysList"
          @input="selectInlineDate"
        ></itf-date-range-picker-inline>
      </div>
    </div>

    <div class="addon-end" v-if="clearable && value && value[0]">
      <slot name="clear">
        <itf-button
          icon
          small
          @click="$emit('input', '')"
        >
          <itf-icon name="close" />
        </itf-button>
      </slot>
    </div>
  </div>
</template>
<script>
import { Vue, Component, Prop, Inject } from 'vue-property-decorator';
import { IMask, IMaskComponent } from 'vue-imask';
import { DateTime } from 'luxon';
import tippy from 'tippy.js';
import itfIcon from '../icon/Icon';
import itfButton from '../button/Button';
import itfDateRangePickerInline from './DateRangePickerInline.vue';
import ITFSettings from '../../ITFSettings';
import itfDatePickerInline from "./DatePickerInline.vue";

export default @Component({
  name: 'itfDateRangePicker',
  components: {
    itfDatePickerInline,
    itfIcon,
    itfButton,
    itfDateRangePickerInline,
    IMaskComponent,
  },
})
class itfDateRangePicker extends Vue {
  @Inject({ default: null }) itemLabel;

  @Prop({ default: () => ([]) }) value;
  @Prop({ type: String, default: 'ISO' }) valueFormat;
  @Prop({ type: String }) displayFormat;
  @Prop({ type: Array }) daysList;
  @Prop({ type: String, default: 'days', validator: (value) => ['days', 'months', 'years'].includes(value) }) startView;
  @Prop({ type: Boolean, default: false }) onlyCalendar;
  @Prop({ type: Boolean, default: false }) clearable;
  @Prop({ type: String, default: '' }) placeholder;
  @Prop({ type: String, default: '' }) prependIcon;
  @Prop({ type: String, default: 'bottom-start' }) placement;
  @Prop({ type: [String, Date], default: '' }) minDate;
  @Prop({ type: [String, Date], default: ''}) maxDate;
  @Prop(Boolean) disabled;
  @Prop(Boolean) compare;
  @Prop({ type: Array }) range; // for compare mode

  focused = false;

  tooltip = null;

  blocks = {
    yyyy: {
      mask: IMask.MaskedRange,
      from: 1970,
      to: 2100,
    },
    MM: {
      mask: IMask.MaskedRange,
      from: 1,
      to: 12,
    },
    dd: {
      mask: IMask.MaskedRange,
      from: 1,
      to: 31,
    },
  };

  get dateFormat() {
    return this.displayFormat || ITFSettings.defaultDisplayDateFormat;
  }

  isInvalid() {
    return this.itemLabel && this.itemLabel.isHasError();
  }

  isSuccess() {
    return this.itemLabel && this.itemLabel.isHasSuccess();
  }

  mounted() {
    // якщо в модалці, то контекст модалки, якщо ні, то аплікейшена
    const context = this.$el.closest('.itf-append-context') || document.body;
    this.tooltip = tippy(this.$refs.group, {
      interactiveBorder: 30,
      interactiveDebounce: 75,
      animation: 'scale',
      arrow: true,
      content: this.$refs.dropdown,
      allowHTML: true,
      trigger: 'click',
      interactive: true,
      placement: this.placement,
      appendTo: context
    });
  }

  get valueAsLuxon() {
    if (!this.value || this.value.length < 2 || !this.value[0] || !this.value[1]) {
      return null;
    }
    if (this.valueFormat === 'ISO') {
      return [
        DateTime.fromISO(this.value[0]),
        DateTime.fromISO(this.value[1]),
      ];
    }
    return [
      DateTime.fromFormat(this.value[0], this.valueFormat),
      DateTime.fromFormat(this.value[1], this.valueFormat),
    ];
  }

  get displayValue() {
    if (!this.valueAsLuxon || this.valueAsLuxon.length < 2) {
      return ['', ''];
    }
    return [
      this.valueAsLuxon[0].toFormat(this.dateFormat),
      this.valueAsLuxon[1].toFormat(this.dateFormat)
    ];
  }

  get minDateLuxon() {
    return this.minDate && this.dateLuxon(this.minDate);
  }

  get maxDateLuxon() {
    return this.maxDate && this.dateLuxon(this.maxDate);
  }

  dateLuxon(date) {
    return (typeof date === 'string' ? DateTime.fromISO(date) : DateTime.fromJSDate(date));
  }

  updateValue(value, index, emitEmpty = false) {
    const val = value && DateTime.fromFormat(value, this.dateFormat);
    if (!val || !val.isValid) {
      if (emitEmpty) {
        this.$emit('input', []);
      }
      return;
    }
    const current = [...(this.value || [])];
    current[0] = current[0] || null;
    current[1] = current[1] || null;
    current[index] = (this.valueFormat === 'ISO') ? val.toISO() : val.toFormat(this.valueFormat);
    if ((this.minDateLuxon && val < this.minDateLuxon) ||
      (this.maxDateLuxon && val > this.maxDateLuxon)
    ) {
      return;
    }
    this.$emit('input', current);
  }

  format(date) {
    return DateTime.fromJSDate(date).toFormat(this.dateFormat);
  }

  parse(str) {
    return DateTime.fromFormat(str, this.dateFormat).toJSDate();
  }

  onFocus() {
    this.focused = true;
  }

  onBlur() {
    this.focused = false;
    if (this.valueAsLuxon && this.valueAsLuxon[0] && this.valueAsLuxon[1] && this.valueAsLuxon[0] > this.valueAsLuxon[1]) {
      if ((this.minDateLuxon && (this.valueAsLuxon[0] < this.minDateLuxon || this.valueAsLuxon[1] < this.minDateLuxon)) ||
        (this.maxDateLuxon && (this.valueAsLuxon[0] > this.maxDateLuxon || this.valueAsLuxon[1] > this.maxDateLuxon))
      ) {
        return;
      }
      this.$emit('input', [this.value[0], this.value[1]]);
    }
  }

  selectInlineDate(date) {
    this.$emit('input', date);
    this.tooltip.hide();
  }
}
</script>
