<template>
  <x-poptip
    ref="datepickerPoptip"
    popper-class="date-poptip"
    class="x-datepicker"
    :placement="placement"
    :append-to-body="appendToBody"
    :position-fixed="positionFixed"
    :viewport="viewport"
    :visible-arrow="visibleArrow"
    :popper-options="popperOptions"
    @on-hide="pickerPoptipHide"
    @on-show="pickerPoptipShow"
  >
    <div slot="reference">
      <slot name="input" :placeholder="placeholder" :value="text" :suffix-icon="suffixIcon" :prefix-icon="prefixIcon" :disabled="disabled" :size="size" :readonly="readonly">
        <x-input
          v-bind="inputProps"
          :value="text"
          :clearable="clearable"
          :placeholder="placeholder"
          :suffix-icon="suffixIcon"
          :prefix-icon="prefixIcon"
          :size="size"
          :validator-icon="false"
          :readonly="readonly"
          @on-clear="empty"
        ></x-input>
      </slot>
    </div>

    <date
      v-if="type==='date'"
      ref="date"
      :value="dateValue"
      :format="format"
      :disabled-date="disabledDate"
      :confirm="confirm"
      :end-time="endTime"
      :hours="hours"
      @change="dateChange"
      @cancel="cancel"
      @confirm="$refs.datepickerPoptip.doClose()"
    ><template slot="confirm"><slot name="confirm"></slot></template></date>
    <daterange
      v-if="type==='daterange'"
      ref="refDaterange"
      :value="dateValue"
      :format="format"
      :confirm="confirm"
      :disabled-date="disabledDate"
      :options="options"
      :options-width="optionsWidth"
      :multiple="multiple"
      :select-index="selectIndex"
      :end-time="endTime"
      :unlink-panels="unlinkPanels"
      :panel-num="panelNum"
      :hours="hours"
      @confirm="$refs.datepickerPoptip.doClose()"
      @change="dateChange"
      @cancel="cancel"
    >
      <template slot="confirm"><slot name="confirm"></slot></template>
      <template slot="options"><slot name="options"></slot></template>
    </daterange>
    <month
      v-if="type==='year' || type==='month'"
      :type="type"
      :value="dateValue"
      @change="dateChange"
    ></month>

  </x-poptip>
</template>

<script>
import { emitter } from '../../../../src/util'
import { xInput } from '../../../vue-input/src/index'
import { xPoptip } from '../../../vue-poptip/src/index'
import date from './panel/date.vue'
import Daterange from './panel/daterange.vue'
import isType from './util/isType.js'
import isValid from './util/isValid.js'
import ishms from './util/ishms.js'
import moment from 'dayjs'
import month from './panel/month.vue'
import { t } from '../../../../src/locale'

export default {
  name: 'xDatepicker',
  components: { date, xPoptip, xInput, Daterange, month },
  mixins: [emitter],
  props: {

    // 日期面板显示或者隐藏
    show: {
      type: [String, Number, Boolean],
      default: false
    },

    // 初始值
    value: {
      type: [Array, String, Number, Date],
      default() {
        return null
      }
    },

    /*
     * 日期类型
     * 选项值: date || daterange || year || month
    */
    type: {
      type: String,
      default: 'date'
    },

    // 展示的日期格式
    format: {
      type: String,
      default: 'YYYY-MM-DD'
    },

    // 不可选日期
    disabledDate: { // eslint-disable-line
      type: Function
    },

    // 是否显示底部控制栏
    confirm: {
      type: [Number, Boolean],
      default: 0
    },

    // 选项
    options: {
      type: [Array, Object],
      default: null
    },

    // 左边快捷选项宽度
    optionsWidth: {
      type: Number,
      default: 150
    },

    // 点击左边快捷栏后是否立即关闭整个日期框
    optionsClickClose: {
      type: Boolean,
      default: true
    },

    /**
     * 日期面板显示方向
     * 选项值: bottom-left || bottom-right || top-left || top-right
     */
    placement: {
      type: String,
      default: 'bottom-start'

    },

    // 是否添加到body
    appendToBody: {
      type: Boolean,
      default: false
    },

    positionFixed: Boolean,

    viewport: Boolean,

    // Popper.js 的可选项
    popperOptions: {
      type: Object,
      default() {
        return {}
      }
    },

    // 文本框描述
    placeholder: {
      type: String,
      default() {
        return t('ans.datepicker.placeholder')
      }
    },

    inputProps: {
      type: Object,
      default() {
        return {}
      }
    },

    clearable: Boolean,

    // disabled
    disabled: {
      type: Boolean,
      default: false
    },

    // // 尺寸，可选值为large、small、default或者不设置
    size: {
      type: String,
      default: 'default'
    },

    suffixIcon: {
      type: String,
      default: ''
    },

    prefixIcon: {
      type: String,
      default: 'ans-icon-calendar'
    },

    // 是否只读
    readonly: {
      type: Boolean,
      default: true
    },

    // 日期区间连接符,在daterange模式下有效
    rangeSeparator: { // eslint-disable-line
      default: ' - '
    },

    // 可选择多个日期，默认一个, 0为无限个
    multiple: {
      type: Number,
      default: 1
    },

    // 多选日期时，点选,指定要选的index, 从0开始
    selectIndex: {
      type: Number,
      default: -1
    },

    // 支持面板个数，在daterange模式下有效
    panelNum: {
      type: Number,
      default: 2
    },

    // 设置结束日期时分秒
    // ['00', '00', '00']
    endTime: {
      type: Array,
      default: null
    },

    // 是否带箭头
    visibleArrow: {
      type: Boolean,
      default: true
    },

    // 在范围选择器里取消两个日期面板之间的联动
    unlinkPanels: {
      type: Boolean,
      default: false
    },
    hours: {
      type: Object,
      default: function() {
        return {
          start: 0,
          end: 24
        }
      }
    }
  },
  data() {
    return {
      text: '',
      dateValue: null,
      dateValueBar: null,
      display: false,

      isChange: true
    }
  },
  watch: {
    value(v, v1) {
      const value = v.toString()
      if (value !== (v1 && v1.toString()) && value !== this.dateValueBar.toString()) {
        this.init(true)
      }
    }
  },
  created() {
    this.init()
  },

  methods: {

    init(isChild) {
      const { dataValue } = this.getDateValue()
      this.setText(dataValue)
      this.dateValue = dataValue
      this.dateValueChange = [...dataValue]
      this.dateValueBar = [...dataValue]
      if (isChild) {
        if (this.type === 'daterange') this.$refs.refDaterange.init(this.dateValue, this.display)
        if (this.type === 'date') this.$refs.date.init(this.dateValue)
      }
    },

    /**
     * 手动设置日期value, 该方法对外
     * @param { Array Date } date confirm模式下是否关闭日期面板
     * @param { Boolean } isClosePoptip confirm模式下是否关闭日期面板
     */
    setValue(date, isClosePoptip = false) {
      const { dataValue } = this.getDateValue(date)
      this.dateChange(dataValue)
      if (this.type === 'daterange') this.$refs.refDaterange.init(dataValue, false)
      if (this.type === 'date') this.$refs.date.init(dataValue)
      if (isClosePoptip) {
        this.doClose()
      }
    },

    // 获取赋值Value
    getDateValue(dValue) {
      const value = dValue || this.value; const dataValue = []
      if (value) {
        if (isType(value) === 'array') {
          // daterange类型的老数据

          if (this.type === 'daterange' && value.length && isType(value[0]) !== 'array') {
            dataValue.push(value)
          } else {
            value.forEach(item => { dataValue.push(item) })
          }
        } else {
          // let isData = isValid(value)

          // 兼容日期区间之前已保存的数据格式 "近xx日" => [['近xx日']]
          this.type === 'daterange' ? dataValue.push([value]) : dataValue.push(value)
        }
      }
      return { dataValue }
    },

    doClose() {
      this.$refs.datepickerPoptip.doClose()
    },

    isConfirm() {
      if (this.confirm || ishms(this.format)) return true
      return false
    },

    dateChange(data, optItem) {
      this.dateValueChange = data
      this.optItem = optItem ? { ...optItem } : null

      const fmtDate = this.fmtDate(data)

      this.setText(data, optItem)

      if (optItem) {
        (this.optionsClickClose && this.multiple === 1) ? this.doClose() : this.$emit('on-text-change', fmtDate, optItem)
        return
      }

      !this.isConfirm() ? this.doClose() : this.$emit('on-text-change', fmtDate, optItem)
    },

    dateFormat(date) {
      return moment(new Date(date)).format(this.format)
    },

    // 获取文本展示文本
    setText(data) {
      if (data && data.length) {
        const type = this.type

        const fmtDate = this.fmtDate(data)

        if (type === 'date') this.text = fmtDate[0]

        if (type === 'daterange') {
          if (data.length === 1) {
            const dataFirst = fmtDate[0]
            this.text = dataFirst.join(this.rangeSeparator)
          } else {
            const text = []
            fmtDate.forEach(o => { text.push(o.join(this.rangeSeparator)) })
            this.text = text
          }
        }

        if (type === 'year' || type === 'month') this.text = fmtDate[0]
      } else {
        this.text = ''
      }
    },

    // 日期选择面板显示
    pickerPoptipShow() {
      this.$emit('on-open-change')
      this.display = true
    },

    //  日期选择面板关闭
    pickerPoptipHide() {
      if (this.isChange) this.change()
      this.$emit('on-close-change')
      this.display = false
      this.isChange = true
    },

    // 清空
    empty() {
      this.dateValue = []
      this.dateValueChange = []
      this.text = ''
      if (this.type === 'daterange') this.$refs.refDaterange.init(this.dateValue)
      if (this.type === 'date') this.$refs.date.init(this.dateValue)
      this.$emit('on-empty')
    },

    // 取消
    cancel() {
      this.isChange = false
      this.$emit('on-clear')
      this.doClose()
    },

    change() {
      if (this.dateValueChange.length) {
        const date = [...this.dateValueChange]
        const fmtDate = this.fmtDate(date)

        if (this.dateValueBar.toString() !== date.toString()) {
          let changeDate = fmtDate; const type = this.type

          if (type === 'date') {
            changeDate = fmtDate[0]
          }

          if (type === 'daterange' && this.multiple === 1) {
            const dataFirst = fmtDate[0]
            changeDate = dataFirst.length === 1 ? dataFirst[0] : dataFirst
          }

          if (type === 'year') {
            changeDate = fmtDate[0]
          }

          if (type === 'month') {
            changeDate = fmtDate[0]
          }
          this.$emit('on-change', changeDate, date, this.optItem)
          this.$emit('change', { value: changeDate, date, option: this.optItem })
          this.$emit('input', changeDate)
          this.dispatch('xFormItem', 'on-form-change', changeDate)
          this.dateValueBar = date
        }
      }
    },

    // 格式化数据数组
    fmtDate(date, optItem) {
      if (date && date.length) {
        const fmtDate = []
        date.forEach(o => {
          if (isType(o) === 'array') {
            const arr = []
            for (let i = 0; i < o.length; i++) {
              isValid(o[i]) ? arr.push(moment(o[i]).format(this.format)) : arr.push(o[i])
            }
            fmtDate.push(arr)
          } else {
            isValid(o) ? fmtDate.push(moment(o).format(this.format)) : fmtDate.push(o)
          }
        })
        return fmtDate
      }
    },

    /**
     * hover选中日期
     * @param {Array Date String} date 传入的选中日期
     */
    onHoverSelect(date) {
      this.$refs.refDaterange.hoverClass(date)
    },

    /**
     * options选项点击
     */
    onOptionsClick(item) {
      this.$refs.refDaterange.optionsClick(item)
    }
  }
}
</script>
