<!--
  Program: Date Picker
  Author: SDL
  Brief: Date Picker Component
-->
<template>
  <div class="d-inline-flex">
    <template v-if="lazyLoad">
      <datepicker
        v-bind="$attrs"
        v-if="!period"
        v-model="date"
        :ref="refKey"
        :bootstrap-styling="true"
        :wrapper-class="wrapClass"
        :language="currentLang"
        :format="customFormatter"
        :minimum-view="minimumView"
        :disabled-dates="disabledDate"
        :disabled="disabled"
        @input="updateDate"
      >
        <template #afterDateInput>
          <button class="btn btn-outline-secondary" type="button" :data-ref="refKey" :disabled="disabled" @click="openPicker(refKey)" v-click-outside="outsideClick">
            <i class="bi bi-calendar"></i>
          </button>
        </template>
      </datepicker>
      <template v-else>
        <datepicker
          v-model="startDate"
          :ref="startRefKey"
          :bootstrap-styling="true"
          :wrapper-class="wrapClass"
          :language="currentLang"
          :format="customFormatter"
          :minimum-view="minimumView"
          :disabled-dates="startDisabledDates"
          :disabled="startDisabled || disabled"
          :placeholder="startPlaceHolder"
          @input="updateStartDate"
        >
          <template #afterDateInput>
            <button class="btn btn-outline-secondary" type="button" :data-ref="startRefKey" :disabled="startDisabled || disabled" @click="openPicker(startRefKey)" v-click-outside="outsideClick">
              <i class="bi bi-calendar"></i>
            </button>
          </template>
        </datepicker>
        <span class="ms-2 me-2 pt-2"> ~ </span>
        <datepicker
          v-model="endDate"
          :ref="endRefKey"
          :bootstrap-styling="true"
          :wrapper-class="wrapClass"
          :language="currentLang"
          :format="customFormatter"
          :minimum-view="minimumView"
          :disabled-dates="endDisabledDates"
          :disabled="endDisabled || disabled"
          :placeholder="endPlaceHolder"
          @input="updateEndDate"
        >
          <template #afterDateInput>
            <button class="btn btn-outline-secondary" type="button" :data-ref="endRefKey" :disabled="endDisabled || disabled" @click="openPicker(endRefKey)" v-click-outside="outsideClick">
              <i class="bi bi-calendar"></i>
            </button>
          </template>
        </datepicker>
      </template>
    </template>
  </div>
</template>
<script>
import Datepicker from './components/Datepicker.vue';
import { mapGetters } from 'vuex';
import moment from 'moment';
import _ from 'lodash';
import SDLUtil from '@/utils/SDLUtil';

export default {
  components: {
    Datepicker,
  },
  emits: ['input', 'moment', 'update:modelValue'],
  props: {
    value: {
      type: [String, Object],
    },
    modelValue: {
      type: [String, Object],
    },
    wrapClass: {
      required: false,
      type: String,
      default: 'wd150',
    },
    // period information
    period: {
      required: false,
      type: Object,
    },
    // minimum unit - ex) When setting to month, picker can be selected on a monthly basis
    minimumView: {
      required: false,
      type: String,
      default: 'day',
    },
    default: {
      required: false,
      type: Boolean,
      default: true,
    },
    disabled: {
      required: false,
      type: Boolean,
      default: false,
    },
    disabledDate: {
      required: false,
      type: Object,
      default: () => {},
    },
    startDisabledDate: {
      required: false,
      type: String,
      default: '',
    },
    endDisabledDate: {
      required: false,
      type: String,
      default: '',
    },
  },
  data() {
    return {
      refKey: _.uniqueId('dp_'),
      startRefKey: _.uniqueId('start_dp_'),
      endRefKey: _.uniqueId('end_dp_'),
      lazyLoad: false,
      date: '',
      startDate: '',
      endDate: '',
      currentLang: null,
      lang: {},
    };
  },
  created() {
    import('./locale/').then(data => {
      this.$i18n.availableLocales.forEach(countryCode => {
        const country = countryCode.replace('_', '-').split('-')[0];
        this.lang[countryCode] = data[country];
      });
      // Applying the language currently set
      this.currentLang = this.lang[this.$i18n.locale];
      // period information initialization
      if (this.period) {
        this.startDate = _.has(this.modelValue, 'startDate') ? moment(this.modelValue.startDate).format(this.standardFormat) : moment().subtract(1, 'M').format(this.standardFormat);
        this.endDate = _.has(this.modelValue, 'endDate') ? moment(this.modelValue.endDate).format(this.standardFormat) : moment().format(this.standardFormat);
        this.updatePeriod();
      } else {
        this.date = this.modelValue ? this.modelValue : moment().format(this.standardFormat);
        this.updateDate(this.date);
      }
      this.lazyLoad = true;
    });
  },
  computed: {
    ...mapGetters({
      locale: 'getLocale',
    }),
    // Start Date Zone Disabled Settings
    startDisabled() {
      return this.period.startDisabled;
    },
    // End Date Zone Disabled Settings
    endDisabled() {
      return this.period.endDisabled;
    },
    // Start date range settings.
    startDisabledDates() {
      return {
        to: moment(this.startDisabledDate).toDate(),
        from: moment(this.endDate).parseZone().toDate(),
      };
    },
    // End date range settings.
    endDisabledDates() {
      return {
        to: moment(this.startDate).toDate(),
      };
    },
    // Start Date PlaceHolder
    startPlaceHolder() {
      return this.period.startPlaceHolder || '';
    },
    // End Date PlaceHolder
    endPlaceHolder() {
      return this.period.endPlaceHolder || '';
    },
    // Date Format by Locale
    dateFormat() {
      return this.minimumView === 'month' ? SDLUtil.getMsgProp('data-format.date.ym') : SDLUtil.getMsgProp('data-format.date.ymd');
    },
    standardFormat() {
      return this.minimumView === 'month' ? 'YYYY-MM' : 'YYYY-MM-DD';
    },
  },
  watch: {
    // Change of date unit
    minimumView() {
      if (this.minimumView === 'day') {
        this.startDate = moment().subtract(1, 'M').format(this.standardFormat);
        this.endDate = moment().format(this.standardFormat);
      }
      this.updatePeriod();
    },
    // locale Change
    locale() {
      this.currentLang = this.lang[this.locale];
    },
    modelValue() {
      if (this.period) {
        this.startDate = _.has(this.modelValue, 'startDate') ? moment(this.modelValue.startDate).format(this.standardFormat) : moment().subtract(1, 'M').format(this.standardFormat);
        this.endDate = _.has(this.modelValue, 'endDate') ? moment(this.modelValue.endDate).format(this.standardFormat) : moment().format(this.standardFormat);
      } else {
        this.date = this.modelValue ? this.modelValue : moment().format(this.standardFormat);
      }
    },
  },
  methods: {
    /**
     * param: param -> Object
     * return: void
     * exception:
     * description : Close when clicking outside the calendar button area
     */
    outsideClick(param) {
      if (_.find(param.evt.path, ['className', 'vdp-datepicker__calendar'])) {
        return;
      }
      if (
        param.evt.target.className.indexOf('prev') > -1 ||
        param.evt.target.className.indexOf('next') > -1 ||
        param.evt.target.className.indexOf('day__month_btn') > -1 ||
        param.evt.target.className.indexOf('month__year_btn') > -1 ||
        (param.evt.target.nodeName === 'SPAN' && param.evt.target.parentNode.nodeName === 'HEADER')
      ) {
        return;
      }
      const calendar = this.$refs[param.source.dataset.ref];
      if (calendar.isOpen) calendar.close(true);
    },
    /**
     * param: date -> Date
     * return: String
     * exception:
     * description : Return to set date format String
     */
    customFormatter(date = moment()) {
      return moment(date).format(this.dateFormat);
    },
    standardFormatter(date = moment()) {
      return moment(date).format(this.standardFormat);
    },
    /**
     * param: refKey -> String
     * return: String
     * exception:
     * description : Activate the calendar by clicking the calendar button
     */
    openPicker(refKey) {
      this.$refs[refKey].showCalendar();
    },
    /**
     * param: value -> Date
     * return: String
     * exception:
     * description : When changing value updates.
     */
    updateDate(value) {
      this.$emit('input', moment(value).format(this.dateFormat));
      this.$emit('update:modelValue', moment(value).format(this.dateFormat));
      this.$emit('moment', moment(value));
    },
    /**
     * param: value -> Date
     * return: String
     * exception:
     * description : Start date change
     */
    updateStartDate(value) {
      this.startDate = value;
      this.updatePeriod();
    },
    /**
     * param: value -> Date
     * return: String
     * exception:
     * description : End date change
     */
    updateEndDate(value) {
      this.endDate = value;
      this.updatePeriod();
    },
    /**
     * param:
     * return: String
     * exception:
     * description : When changing the period updates
     */
    updatePeriod() {
      this.$emit('input', {
        startDate: this.standardFormatter(this.startDate),
        endDate: this.standardFormatter(this.endDate),
      });
      this.$emit('update:modelValue', {
        startDate: this.standardFormatter(this.startDate),
        endDate: this.standardFormatter(this.endDate),
      });
    },
  },
};
</script>

<style>
.wd150 {
  width: 150px !important;
}
.vdp-datepicker__calendar {
  z-index: 118 !important;
}
.rtl {
  direction: rtl;
}
.vdp-datepicker {
  position: relative;
  text-align: left;
}
.vdp-datepicker * {
  box-sizing: border-box;
}
.vdp-datepicker__calendar {
  position: absolute;
  z-index: 100;
  background: #fff;
  width: 300px;
  border: 1px solid #ccc;
}
.vdp-datepicker__calendar header {
  display: block;
  line-height: 40px;
}
.vdp-datepicker__calendar header span {
  display: inline-block;
  text-align: center;
  width: 71.42857142857143%;
  float: left;
}
.vdp-datepicker__calendar header .prev,
.vdp-datepicker__calendar header .next {
  width: 14.285714285714286%;
  float: left;
  text-indent: -10000px;
  position: relative;
}
.vdp-datepicker__calendar header .prev:after,
.vdp-datepicker__calendar header .next:after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translateX(-50%) translateY(-50%);
  border: 6px solid transparent;
}
.vdp-datepicker__calendar header .prev:after {
  border-right: 10px solid #000;
  margin-left: -5px;
}
.vdp-datepicker__calendar header .prev.disabled:after {
  border-right: 10px solid #ddd;
}
.vdp-datepicker__calendar header .next:after {
  border-left: 10px solid #000;
  margin-left: 5px;
}
.vdp-datepicker__calendar header .next.disabled:after {
  border-left: 10px solid #ddd;
}
.vdp-datepicker__calendar header .prev:not(.disabled),
.vdp-datepicker__calendar header .next:not(.disabled),
.vdp-datepicker__calendar header .up:not(.disabled) {
  cursor: pointer;
}
.vdp-datepicker__calendar header .prev:not(.disabled):hover,
.vdp-datepicker__calendar header .next:not(.disabled):hover,
.vdp-datepicker__calendar header .up:not(.disabled):hover {
  background: #eee;
}
.vdp-datepicker__calendar .disabled {
  color: #ddd;
  cursor: default;
}
.vdp-datepicker__calendar .flex-rtl {
  display: flex;
  width: inherit;
  flex-wrap: wrap;
}
.vdp-datepicker__calendar .cell {
  display: inline-block;
  padding: 0 5px;
  width: 14.285714285714286%;
  height: 40px;
  line-height: 40px;
  text-align: center;
  vertical-align: middle;
  border: 1px solid transparent;
}
.vdp-datepicker__calendar .cell:not(.blank):not(.disabled).day,
.vdp-datepicker__calendar .cell:not(.blank):not(.disabled).month,
.vdp-datepicker__calendar .cell:not(.blank):not(.disabled).year {
  cursor: pointer;
}
.vdp-datepicker__calendar .cell:not(.blank):not(.disabled).day:hover,
.vdp-datepicker__calendar .cell:not(.blank):not(.disabled).month:hover,
.vdp-datepicker__calendar .cell:not(.blank):not(.disabled).year:hover {
  border: 1px solid #4bd;
}
.vdp-datepicker__calendar .cell.selected {
  background: #4bd;
}
.vdp-datepicker__calendar .cell.selected:hover {
  background: #4bd;
}
.vdp-datepicker__calendar .cell.selected.highlighted {
  background: #4bd;
}
.vdp-datepicker__calendar .cell.highlighted {
  background: #cae5ed;
}
.vdp-datepicker__calendar .cell.highlighted.disabled {
  color: #a3a3a3;
}
.vdp-datepicker__calendar .cell.grey {
  color: #888;
}
.vdp-datepicker__calendar .cell.grey:hover {
  background: inherit;
}
.vdp-datepicker__calendar .cell.day-header {
  font-size: 85%;
  white-space: nowrap;
  cursor: inherit;
}
.vdp-datepicker__calendar .cell.day-header:hover {
  background: inherit;
}
.vdp-datepicker__calendar .month,
.vdp-datepicker__calendar .year {
  width: 33.333%;
}
.vdp-datepicker__clear-button,
.vdp-datepicker__calendar-button {
  cursor: pointer;
  font-style: normal;
}
.vdp-datepicker__clear-button.disabled,
.vdp-datepicker__calendar-button.disabled {
  color: #999;
  cursor: default;
}
</style>
