<template>
  <div class="el-calendar__day">
    <!-- 头部 -->
    <div class="el-calendar__day--header">
      <div class="el-calendar__day--header-date">
        {{showDate}}
      </div>
      <div class="el-calendar__day--header-event" :style="{ height: getHeaderEventHeight() }">
        <div class="el-calendar__day--header-left">
          <span v-if="showCollapse"><i class="el-icon-arrow-right" v-if="showFlatEvents.length > 3" @click="handleCollapse" :style="collapseStyle"></i></span>
        </div>
        <div class="el-calendar__day--header-event-wrap">
          <ul class="el-calendar__day--header-event-grid">
            <template v-for="(item,index) in showFlatEvents">
              <li class="el-calendar__day--header-event-li" :class="[item.class]"
                :key="index" v-if="showFlatEvent(item)"
                :style="{left: `calc(${item.leftPos * 100}% + 4px)`, width: `calc(${item.width * 100}% - 8px)`, top: `calc(${item.topInd}em + 4px)`}">
                <el-popover v-if="tempPopper || item.popper" :key="item.key" placement="top" :maxHeight="item.maxHeight || 200" :width="item.popoverWidth || 450" :trigger="popoverTrigger || 'hover'" :title="item.title || ''" :open-delay="item.openDelay || 400" :close-delay="item.closeDelay || 300">
                  <popper-dom v-if="tempPopper" :item="item" :render="tempPopper"/>
                  <popper-dom v-else :item="item" :render="item.popper"/>
                  <li :key="item.key || i"
                    class="el-calendar-week--events-li"
                    slot="reference">
                    <div @click="clickItem(item)" class="el-calendar__day--header-event-item" :class="{'is-history': isHistoryTime(item.start,item.end)}" :style="{...item.style, ...item.leftStyle}" v-html="item.children"></div>
                  </li>
                </el-popover>
                <div v-else @click="clickItem(item)" class="el-calendar__day--header-event-item"  v-html="item.children" :class="{'is-history': isHistoryTime(item.start,item.end)}"></div>
              </li>
              <li :key="'last'+index" v-if="item.topInd === 0 && showFlatEvents.length > 3 && !collapse" class="el-calendar__day--header-event-li" :style="{left: `calc(${item.leftPos * 100}% + 4px)`, width: `calc(14.3% - 8px)`, top: `calc(${item.topInd}em + 44px)`}">
                <div @click="clickItem(item)" class="el-calendar__day--header-event-li-last" :class="{'is-history': isHistoryTime(item.start,item.end)}">日程汇总</div>
              </li>
            </template>
          </ul>
        </div>
      </div>
    </div>
    <!-- 主体 -->
    <div class="el-calendar__day--main">
      <el-scrollbar
        class="el-calendar__day--main--wrapper"
        wrap-style="max-height: inherit;"
        view-class="el-calendar__day--main--list"
        noresize
        tag="div">
        <div class="el-calendar__day--main--left">
          <div class="el-calendar__day--main-timeline" :style="{top: `${timelineTop}px`}"></div>
          <div class="el-calendar__day--main-now" :style="{top: `${timelineTop - 55}px`}">{{timelineDesc}}</div>
          <ul class="el-calendar__day--main--times">
            <li class="el-calendar__day--main--time" v-for="(item,index) in timeList" :key="index">
              <span>{{item}}</span>
            </li>
          </ul>
        </div>
        <div class="el-calendar__day--main--grid">
          <ul class="el-calendar__day--main--skeleton" ref="">
            <li :data-time="time" v-for="(time, index) in mainSkeleton" :key="index"
              :class="{'el-calendar__day--main--row': index % 2 === 0}"></li>
          </ul>
          <ul class="el-calendar__day--main-grid">
            <template v-for="(item,index) in parseHourEvents">
              <li
                class="el-calendar__day--main-li"
                :class="{
                  'el-calendar__day--main-li-left': item.left === 0 && item.width !== 50 &&item.width !== 100,
                  'el-calendar__day--main-li-right': item.left + item.width === 100 && item.width !== 50 && item.width !== 100,
                  'el-calendar__day--main-li-columnhelf-left': item.width === 50 && item.left == 0,
                  'el-calendar__day--main-li-columnhelf-right': item.width === 50 && item.left + item.width === 100,
                  'el-calendar__day--main-li-rowhelf-top': (item.startIndex%2 === 0 && item.height % 60 !== 0) || (item.startIndex%2 !== 0 && item.height % 60 === 0),
                  'el-calendar__day--main-li-rowhelf-bottom': item.startIndex%2 === 1,
                }"
                :style="{
                  width: `calc(${item.width}%)`,
                  left: `calc(${item.left}%)`,
                  top: `${item.top}px`,
                  height: `${item.height}px`}"
                :key="index">
                <div
                  class="el-calendar__day--main-item"
                  :class="{'is-history': item.end.getTime() - Date.now() < 0}">
                  <el-popover v-if="tempPopper || item.popper" :key="item.key" placement="top" :maxHeight="item.maxHeight || 200" :width="item.popoverWidth || 450" :trigger="popoverTrigger || 'hover'" :title="item.title || ''" :open-delay="item.openDelay || 400" :close-delay="item.closeDelay || 300">
                    <popper-dom v-if="tempPopper" :item="item" :render="tempPopper"/>
                    <popper-dom v-else :item="item" :render="item.popper"/>
                    <li ref="contentElement" :key="item.key || i"
                      class="el-calendar-week--events-li"
                      slot="reference">
                      <div @click="clickItem(item)" class="el-calender__day--main-item-content" :style="{...item.style, ...item.leftStyle, ...webkitLineClamp(item.height - 8) }" v-html="item.children"></div>
                    </li>
                  </el-popover>
                  <div v-else @click="clickItem(item)" class="el-calender__day--main-item-content" v-html="item.children" :style="webkitLineClamp(item.height - 8)"></div>
                </div>
                <!-- <div class="el-calendar__day--main-item"  v-html="item.children"
                  :class="{'is-history': item.end.getTime() - Date.now() < 0}"></div> -->
              </li>
            </template>
          </ul>
        </div>
      </el-scrollbar>
    </div>
  </div>
</template>

<script>
  import { getTimeNumber } from 'modesign-ui/src/utils/date-util';
  import Locale from 'modesign-ui/src/mixins/locale';
  import fecha from "modesign-ui/src/utils/date";
  import ElScrollbar from 'modesign-ui/packages/scrollbar';

  export default {
    mixins: [Locale],
    
    components: { 
      popperDom: {
        functional: true,
        props: {
          render: Function,
          item: {
            type: Object,
            default: () => {}
          }
        },
        render: (h, ctx) => {
          const params = {}
          if (ctx.props.item) {
            params.item = ctx.props.item
          }
          return ctx.props.render(h, params)
        }
      },
      ElScrollbar
    },

    props: {
      date: {
        default: new Date()
      },
      selectedDay: String, // formated date yyyy-MM-dd
      events: {
        type: Array,
        default: () => []
      },
      // 节日列表
      festivals: {
        type: Array,
        default: () => {
          return []
        }
      },
    },

    computed: {
      showDate() {
        const { selectedDay, date } = this
        return selectedDay ? selectedDay : fecha.format(date, "yyyy-MM-dd")
      },
      // 事件大于等于三个才显示icon
      showCollapse() {
        const { showFlatEvents } = this
        const list = showFlatEvents.filter(item => item.width) || []
        return list.some(i => i.topInd >= 3)
      }
    },

    data() {
      return {
        showFlatEvents: [], // 将parseEvents拍平
        parseEvents: [], // 解析过的一天以上的事件
        dayEvents: [], // 一天以上的事件
        hourEvents: [], // 一天内的事件
        // parseHourEvents: new Array(48).fill(), // 解析过的一天内的事件
        parseHourEvents: [], // 解析过的一天内的事件
        // headerMap: new Array(WEEKSLENGTH).fill().map((x,i) => i + this.firstDayOfWeek),
        dayRange: [0, 0], // 本周的时间范围 时间戳
        timeList: this.getTimeList(),
        mainSkeleton: this.getMainSkeleton(),
        dayIndex: 0,
        timelineDesc: '',
        timelineTop: 0,
        interval: null,
        collapse: false, // 是否展开收缩
        collapseStyle: {},
        tempPopper: null,
        popoverTrigger: null
      };
    },

    watch: {
      date() {
        this.clearEvents();
        this.init();
      },

      events: {
        deep: true,
        handler() {
          this.clearEvents();
          this.init();
        }
      }
    },

    mounted() {
      this.init();
      this.getCurrentTimeline();
      this.interval = setInterval(this.getCurrentTimeline, 60 * 1000);
    },

    beforeDestroy() {
      clearInterval(this.interval);
    },
  
    methods: {
      // 初始化页面或更新页面信息时
      init() {
        const val = this.events;
        if (val && val.length > 0 && val[0].popper) {
          this.popoverTrigger = val[0].popoverTrigger
          if (val[0].popperTemplate) {
            this.tempPopper = val[0].popper
          }
        }
        // this.setRangeDate();
        this.splitEvents();
        this.hourEventsParse();
      },
      getCurrentTimeline() {
        const current = new Date();
        const hour = current.getHours();
        const minute = current.getMinutes();
        this.timelineTop = hour * 60 + Math.round(minute / 60 * 60);
        this.timelineDesc = hour <= 12 ? `上午${hour}时${minute}分` : `下午${hour - 12}时${minute}分`
      },
      clearEvents() {
        this.parseEvents = [];
        this.showFlatEvents = [];
        this.dayEvents = [];
        this.hourEvents = [];
        this.parseHourEvents = [];
      },
      getTimeList() {
        let result = [];
        const arr = [];
        const arr1 = ['上午12时'];
        result.push('');
        for (let i = 1; i < 12; i++) {
          arr.push(`上午${i}时`);
          arr1.push(`下午${i}时`);
        }
        result = result.concat(arr, arr1);
        return result;
      },
      getMainSkeleton() {
        return Array.from({length: 50}).map((i, index) => {
          var a = index %2;
          var min = a===0 ? '00' : '30' ;
          let hour = Math.floor(index/2);
          return `${hour < 0 ? `0${hour}` : hour}:${min}`
        });
      },
      // 过滤非本周任务，并拆分分为一天以上和一天内的
      splitEvents() {
        const { events } = this
        this.showFlatEvents = events.reduce((p, n) => {
          const { start, end } = n
          // 在事件的时间范围内，且不属于当天的事件
          if (this.isInTodayRange(start, end) && !this.inTodayRange(start, end)) {
            const item = { ...n }
            if (item.allDay) item.dateRange = 1
            return [...p, item]
          } else {
            return [...p]
          }
        }, []).sort((a, b) => {
          return a.start - b.start;
        }).map((i, index) => {
          const { start, end } = i
          const item = {
            ...i,
            width: 1,
            topInd: index,
            leftPos: 0
          }
          if (i.allDay) item.width = 1
          return item
        })
        this.hourEvents = events.filter(i => {
          const { start, end } = i
          return this.inTodayRange(start, end)
        })
      },

      // 开始时间和结束时间都是今天的事件
      inTodayRange(start, end) {
        const { date } = this
        const todayMillSeconds = getTimeNumber(date)
        const startMillSeconds = getTimeNumber(start)
        const endMillSeconds = getTimeNumber(end)
        return startMillSeconds === endMillSeconds && startMillSeconds === todayMillSeconds
      },

      // 事件的时间范围是否包含今天 包括allDay 
      isInTodayRange(start, end) {
        const { date } = this
        const todayMillSeconds = getTimeNumber(date)
        const startMillSeconds = getTimeNumber(start)
        const endMillSeconds = getTimeNumber(end)
        return todayMillSeconds >= startMillSeconds && todayMillSeconds <= endMillSeconds || (!end && todayMillSeconds === startMillSeconds)
      },
      
      // 计算el-calendar__day--header-event的高度
      getHeaderEventHeight() {
        // if (!this.showFlatEvents.length) return 0
        if (this.showFlatEvents.length <= 3) return `calc(3em + 9px)`
        if(this.collapse) {
          return `calc(${this.showFlatEvents.length}em + 9px)`
        } else {
          if(this.showFlatEvents.length > 2) {
            return `calc(3em + 9px)`
          }
          return `calc(${this.showFlatEvents.length}em + 9px)`
        }
      },

      // 对比两个元素是否有交集（是否在一个连续区间内）
      intersection(event1, evnet2) {
        const { startIndex: start1, endIndex: end1 } = event1
        const { startIndex: start2, endIndex: end2 } = evnet2
        if (start1 <= start2 && end1 >= start2) return true
        if ( start1 >= start2 && start1 <= end2) return true
        if (start1 <= start2 && end1 >= end2) return true
        if (start2 <= start1 && end2 >= end1) return true
        return false
      },

      // 格式化事件
      formatEvent(arr) {
        const group = []
        const data = [...arr].sort((a, b) => {
          if (a.startIndex === b.startIndex) {
            return (a.endIndex - a.startIndex) - (b.endIndex - b.startIndex)
          } else {
            return a.startIndex - b.startIndex
          }
        }).map((i) => {
          return {
            ...i
          }
        })
        // 给事件进行分组，连续交叉事件为一组
        data.forEach((i) => {
          const inGroup = group.find(item => {
            return (item).some(items => this.intersection(items, i))
          })
          if (!inGroup) {
            group.push([i])
          } else {
            inGroup.push(i)
          }
        })

        group.forEach((i) => {
          const list = i
          // 每一组的每一个事件赋值left，top
          list.forEach((item, index) => {
            const beforeList = list.slice(0, index + 1)
            const active = beforeList.filter(i => i.endIndex < item.startIndex && !i.noCheck)
            if (active && active.length) {
              active[0].noCheck = true
              item.refresh = () => {
                item.width = active[0].width
                item.left = active[0].left
                item.hasMove = true
              }
              item.refresh()
            }
            beforeList.filter(item => !item.hasMove).forEach((i, index, arr) => {
              i.width = 100 / arr.length
              i.left = i.width * index
            })
            beforeList.filter(item => item.hasMove).forEach(i => {
              i.refresh && i.refresh()
            })
          })
        })
        return group.reduce((p, n) => { return [...p, ...n] }, [])
      },

      // 解析一日内的事件 //定义每个事件的位置
      hourEventsParse() {
        const liItemHeight = 30;
        this.parseHourEvents = this.formatEvent(this.hourEvents.map(i => {
          const { start, end } = i
          const startHour = start.getHours()
          const startMinute = start.getMinutes()
          const endHour = end.getHours()
          const endMinute = end.getMinutes()
          const startIndex = startHour*2 + (startMinute >=30 &&startMinute <=60 ? 1 : 0)
          const endIndex = endHour*2 + (endMinute === 0 ? -1 : endMinute > 0 && endMinute <= 30 ? 0 : 1 )
          return {
            ...i,
            startIndex,
            endIndex,
            height: (endIndex - startIndex + 1) *liItemHeight,
            top: startIndex * liItemHeight
          }
        }))
        // this.hourEvents.forEach(item => {
        //   const itemInfo = { ...item };
        //   const { start, end } = item;
        //   const startIndex = start.getHours() * 2 + Math.round(start.getMinutes() / 30);
        //   const endIndex = end.getHours() * 2 + Math.round(end.getMinutes() / 30);
        //   // 开始结束时间在同一天
        //   itemInfo.height = (endIndex - startIndex) * liItemHeight - ((endIndex - startIndex)%2 == 0 ? 8 : 4);
        //   (this.parseHourEvents[startIndex] || (this.parseHourEvents[startIndex] = [])).push(itemInfo);
        // })
      },

      // 和当前时间对比是否在当前时间之前
      isHistoryTime(starttime,endtime) {
        if(endtime) {
          return endtime.getTime() - Date.now() < 0
        } else {
          const beforeDawn = new Date(new Date().setHours(0, 0, 0, 0)) // 凌晨
          if(starttime.getTime() >= beforeDawn) {
            return false
          } else {
            return true
          }
        }
      },

      showFlatEvent(item) {
        if(this.collapse) {
          return true
        }
        return this.showFlatEvents.length > 3 ? item.width && item.topInd < 2 : item.width && item.topInd < 3
      },
      handleCollapse(){
        this.collapse = !this.collapse;
        if(!this.collapse) {
          this.collapseStyle = {
            transform: "rotate(90deg)"
          }
        } else {
          this.collapseStyle = {
            transform: "rotate(-90deg)"
          }
        }
      },

      // 点击事件
      clickItem(item) {
        this.$emit('clickItem', item)
      },
      // 计算-webkit-line-clamp
      webkitLineClamp(itemHeight) {
        const lineHeight = 22
        const maxLines = Math.floor(itemHeight / lineHeight)
        return maxLines > 1 ? { '-webkit-line-clamp': maxLines } : { '-webkit-line-clamp': 1, 'padding': '1px 8px' }
      }
    }
  };
</script>
