<template>
  <div class="l-flex c-step">
    <div class="l-flex__none c-step__column large">
      <div>
        <slot />
        <div class="c-sibling-item--v u-font-size--sm">上播方式</div>
        <el-select
          v-model="eventOptions.freq"
          class="c-sibling-item--v near"
        >
          <el-option
            v-for="option in freqOptions"
            :key="option.value"
            :label="option.label"
            :value="option.value"
          />
        </el-select>
        <template v-if="isOnce">
          <div class="c-sibling-item--v u-font-size--sm u-required">开始时间</div>
          <el-date-picker
            v-model="eventOptions.start"
            class="c-sibling-item--v near"
            type="datetime"
            placeholder="请选择开始时间"
            value-format="yyyy-MM-dd HH:mm:ss"
            :picker-options="pickerOptions"
            @change="onDateTimeChange('start')"
          />
          <div class="c-sibling-item--v u-font-size--sm u-required">结束时间</div>
          <el-date-picker
            v-model="eventOptions.until"
            class="c-sibling-item--v near"
            type="datetime"
            popper-class="is-hide-now"
            :disabled="!eventOptions.start"
            placeholder="请选择结束时间"
            :default-value="defaultEndDateTime"
            value-format="yyyy-MM-dd HH:mm:ss"
            :picker-options="endPickerOptions"
            @change="onDateTimeChange('until')"
          />
        </template>
        <template v-if="isWeekly">
          <div class="c-sibling-item--v u-font-size--sm u-required">每周</div>
          <el-checkbox-group
            v-model="eventOptions.byDay"
            class="l-flex--row c-sibling-item--v near"
            size="mini"
            fill="#1c5cb0"
          >
            <el-checkbox-button
              v-for="week in weeks"
              :key="week.value"
              :label="week.value"
            >
              {{ week.label }}
            </el-checkbox-button>
          </el-checkbox-group>
          <div class="c-sibling-item--v u-font-size--sm u-required">开始时间</div>
          <el-time-picker
            v-model="eventOptions.startTime"
            class="c-sibling-item--v near"
            placeholder="请选择开始时间"
            value-format="HH:mm:ss"
            :clearable="false"
          />
          <div class="c-sibling-item--v u-font-size--sm u-required">结束时间</div>
          <el-time-picker
            v-model="eventOptions.endTime"
            class="c-sibling-item--v near has-info"
            data-info="结束时间小于等于开始时间为跨天播放"
            placeholder="请选择结束时间"
            value-format="HH:mm:ss"
            :clearable="false"
          />
          <div class="c-sibling-item--v u-font-size--sm u-required">生效日期</div>
          <el-date-picker
            v-model="eventOptions.start"
            class="c-sibling-item--v near"
            type="date"
            placeholder="请选择生效日期"
            value-format="yyyy-MM-dd HH:mm:ss"
            :picker-options="pickerOptions"
            @change="onDateTimeChange('start')"
          />
          <div class="c-sibling-item--v u-font-size--sm u-required">失效日期</div>
          <el-date-picker
            v-model="eventOptions.until"
            class="c-sibling-item--v near has-info"
            data-info="失效日期当天不执行"
            type="date"
            :disabled="!eventOptions.start"
            placeholder="请选择失效日期"
            value-format="yyyy-MM-dd HH:mm:ss"
            :picker-options="endPickerOptions"
            @change="onDateTimeChange('until')"
          />
        </template>
      </div>
    </div>
    <event-target-picker
      ref="eventTargetPicker"
      :event-target="eventTarget"
      class="l-flex__fill c-step__column"
      v-bind="$attrs"
    />
  </div>
</template>

<script>
import {
  ONE_DAY,
  EventPriority,
  EventFrequency
} from '@/constant'
import {
  isMoreThanOneWeek,
  getNearestHitDate,
  isOverDay,
  toDateStr
} from '@/utils/event'

export default {
  name: 'EventPicker',
  props: {
    event: {
      type: Object,
      default: null
    },
    priority: {
      type: Number,
      default: EventPriority.SCHEDULING
    }
  },
  data () {
    return {
      weeks: [
        { value: '0', label: '日' },
        { value: '1', label: '一' },
        { value: '2', label: '二' },
        { value: '3', label: '三' },
        { value: '4', label: '四' },
        { value: '5', label: '五' },
        { value: '6', label: '六' }
      ],
      freqOptions: [
        { value: EventFrequency.ONCE, label: '时段播放' },
        { value: EventFrequency.WEEKLY, label: '周期播放' }
      ],
      eventOptions: null
    }
  },
  computed: {
    isOnce () {
      return this.eventOptions.freq === EventFrequency.ONCE
    },
    isWeekly () {
      return this.eventOptions.freq === EventFrequency.WEEKLY
    },
    pickerOptions () {
      return {
        disabledDate: this.isDisableDate
      }
    },
    endPickerOptions () {
      return {
        disabledDate: this.isDisableEndDate
      }
    },
    defaultEndDateTime () {
      if (this.eventOptions.start) {
        const date = new Date(this.eventOptions.start)
        date.setDate(date.getDate() + 1)
        return `${toDateStr(date)} 00:00:00`
      }
      return null
    }
  },
  watch: {
    event: {
      handler () {
        this.init()
      },
      immediate: true
    }
  },
  methods: {
    isDisableDate (date) {
      return date <= Date.now() - ONE_DAY
    },
    isDisableEndDate (date) {
      if (date <= Date.now() - ONE_DAY) {
        return true
      }
      const startDate = this.eventOptions.start
      if (startDate) {
        if (this.isWeekly) {
          return date <= new Date(startDate)
        }
        return date < new Date(startDate.replace(/\d{2}:\d{2}:\d{2}$/, '00:00:00'))
      }
      return false
    },
    init () {
      const { freq, byDay, target, ...options } = {
        freq: EventFrequency.ONCE,
        start: null,
        until: null,
        startTime: '00:00:00',
        endTime: '00:00:00',
        ...this.event
      }

      this.eventOptions = {
        ...options,
        freq,
        byDay: byDay ? byDay.split(',') : []
      }

      this.eventTarget = target || {}
    },
    onDateTimeChange (type) {
      const { start, until } = this.eventOptions
      if (start && until && start > until) {
        if (type === 'start') {
          this.eventOptions.until = start
        } else {
          this.eventOptions.start = until
        }
      }
    },
    onError (message) {
      this.$message({
        type: 'warning',
        message
      })
      return null
    },
    createWeeklyEvent () {
      const { start, until, byDay, startTime, endTime } = this.eventOptions
      if (byDay.length === 7 && startTime === endTime) {
        return {
          priority: this.priority,
          freq: EventFrequency.ONCE,
          start: start.replace(/\d{2}:\d{2}:\d{2}$/, startTime),
          until: until.replace(/\d{2}:\d{2}:\d{2}$/, startTime)
        }
      }
      const byDayValue = byDay.join(',')
      const isOver = isOverDay({ startTime, endTime })
      const startWeek = new Date(start).getDay()
      const startDate = start.replace(/\d{2}:\d{2}:\d{2}$/, byDayValue.includes(startWeek) || isOver && byDayValue.includes((startWeek + 6) % 7) ? startTime : '00:00:00')
      const untilDate = until && until.replace(/\d{2}:\d{2}:\d{2}$/, isOver && byDayValue.includes((new Date(until).getDay() + 6) % 7) ? endTime : '00:00:00')
      const event = {
        priority: this.priority,
        freq: EventFrequency.WEEKLY,
        start: startDate,
        until: untilDate,
        byDay: byDayValue,
        startTime,
        endTime
      }
      if (untilDate && !isMoreThanOneWeek(new Date(untilDate) - new Date(startDate)) && !getNearestHitDate(event, startDate, untilDate)) {
        return this.onError('有效日期内无法触发')
      }
      return event
    },
    createOnceEvent () {
      const { start, until } = this.eventOptions
      return {
        priority: this.priority,
        freq: EventFrequency.ONCE,
        start, until
      }
    },
    createEvent () {
      if (this.isWeekly) {
        return this.createWeeklyEvent()
      }
      return this.createOnceEvent()
    },
    getValue () {
      const { start, until } = this.eventOptions
      if (this.isOnce) {
        if (!start) {
          return this.onError('请选择开始时间')
        }
        if (!until) {
          return this.onError('请选择结束时间')
        }
        if (start === until) {
          return this.onError('开始时间与结束时间不能一样')
        }
      }
      if (this.isWeekly) {
        const { byDay, startTime, endTime } = this.eventOptions
        if (!byDay.length) {
          return this.onError('请选择生效星期')
        }
        if (!startTime) {
          return this.onError('请选择开始时间')
        }
        if (!endTime) {
          return this.onError('请选择结束时间')
        }
        if (!start) {
          return this.onError('请选择生效日期')
        }
        if (!until) {
          return this.onError('请选择失效日期')
        }
        if (start.split(' ')[0] === until.split(' ')[0]) {
          return this.onError('生效日期与失效日期不能一样')
        }
      }
      if (until && new Date(until).getTime() <= Date.now()) {
        return this.onError('结束时间小于当前时间，请配置有效的生效时间')
      }

      const target = this.$refs.eventTargetPicker.getValue()
      if (!target) {
        return null
      }
      return {
        ...this.createEvent(),
        target
      }
    },
    getEventTargetPicker () {
      return this.$refs.eventTargetPicker
    }
  }
}
</script>
