<template>
  <div :style="{height: sort < total ? '70px' : '60px'}" class="ed-flow-item">
    <div ref="flowItemList" :style="listStyles" class="ed-flow-item--list">
      <template v-for="(item, index) in flowItem">
        <div :key="index" :style="itemBoxStyle(item, index)" class="flow-item-box">
          <!-- 中断日期 -->
          <el-tooltip v-if="getStopDate(item).length > 0 || getStopDateArray(item).length > 0"
                      :visible-arrow="false"
                      class="item" effect="dark" placement="top-start" popper-class="ed-flow-item--popper">
            <div slot="content" v-html="getStopDateTips(item)"></div>
            <div class="ed-flow-item--stop">
              <template v-for="(stopArr, stopArr_index) in getStopDateArray(item)">
                <span :key="`starr${stopArr_index}`" :style="stopDateArrayStyle(item, stopArr)"
                      class="item--stop-vertical array"></span>
              </template>

              <template v-for="(stop, stop_index) in getStopDate(item)">
                <span :key="'st'+stop_index" :style="stopDateStyle(stop, stop_index)"
                      class="item--stop-vertical"></span>
              </template>
            </div>
          </el-tooltip>

          <!-- 无数据时间段 -->
          <template v-for="(schedule, sc) in getSchedule(item)">
            <div :key="'sc' + sc" :class="flowItemBoxClass(index, sc===getSchedule(item).length-1)"
                 :style="getScheduleStyle(schedule, item)"
                 class="ed-flow-item--schedule"></div>
          </template>

          <!-- 开始日期or结束日期 -->
          <template>
            <div v-if="isStartM(index) && !isEndM(index)"
                 :style="getStartStyle(item, 'start')" class="item-start-date">
              <span class="item-start-date--text">{{ startDate }}</span>
            </div>
            <div v-if="!isStartM(index) && isEndM(index)"
                 :style="getEndStyle(item, 'end')" class="item-end-date">
              <span :style="getEndTxtStyle(item)" class="item-start-date--text">{{ endDate }}</span>
            </div>
          </template>


          <!-- 月份标签 -->
          <div :style="scaleStyle(item, index)" class="ed-flow-item--scale">
            <span>|</span>
            <div>
              <span v-if="(item.value===1 || isStartM(index)) && !isEndM(index)">{{ item.label + '年' }}</span>
              <span>{{ item.value }}{{ (item.value === 1 || isStartM(index)) && !isEndM(index) ? '月' : "" }}</span>
            </div>
          </div>

          <div v-if="isEndM(index)" :style="scaleStyleLast" class="ed-flow-item--scale-last">
            <span>|</span>
            <div>{{ getEndDate(item) }}</div>
          </div>
        </div>
      </template>
    </div>

    <div v-if="isOdd && sort!==total" :style="getSortStyle()" class="ed-flow-item--sort"></div>
    <div v-if="!isOdd && sort!==total" :style="getSortStyle()" class="ed-flow-item--sort" style="float: right;"></div>
  </div>
</template>

<script>
import {getDate, getDay, getFullYear, getMonth} from "../../../tools/date-format";
import {getVarType}                             from "../../../tools/utils";

export default {
  name: "EdFlowItem",
  props: {
    //
    flowItem: {
      type: Array,
      default: () => []
    },

    width: {
      type: Number,
      default: 0
    },

    // 开始日期
    start: {
      type: String,
      default: ''
    },

    // 结束日期
    end: {
      type: String,
      default: ''
    },

    // item数量
    total: {
      type: Number,
      default: 0
    },

    // item年份
    year: {
      type: Number,
      default: 0
    },

    // item序号
    sort: {
      type: Number,
      default: 0
    },

    // 无数据时间段
    stopDate: {
      type: Array,
      default: () => []
    },

    // 中断日期
    notDate: {
      type: Array,
      default: () => []
    },
  },
  data() {
    return {
      ItemList: [],
      flowItemClass: ""
    }
  },
  computed: {
    // 判断奇数偶数
    isOdd() {
      return this.sort % 2 === 0
    },
    isStartM() {
      return (index) => {
        return this.sort === 1 && index === 0
      }
    },
    isEndM() {
      return (index) => {
        return this.sort === this.total && index === this.flowItem.length - 1
      }
    },
    startDate() {
      let M = getDate(this.start).getMonth() + 1
      let D = getDate(this.start).getDate()
      return M + '月' + D + '日'
    },
    endDate() {
      let M = getDate(this.end).getMonth() + 1
      let D = getDate(this.end).getDate()
      return M + '月' + D + '日'
    },
    flowItemBoxClass() {
      return (index, isLast) => {
        if (this.isEndM(index) && isLast) {
          return !this.isOdd ? 'ed-flow-item--schedule-oddEnd' : 'ed-flow-item--schedule-evenEnd'
        }
      }
    },
    listStyles() {
      return {
        'flex-direction': this.isOdd ? 'row-reverse' : 'row'
      }
    },
    scaleStyle() {
      return (item, index) => {
        let startOrEnd = this.isStartM(index) || item.value === 1
        if (!this.isOdd) {
          return {
            'left': startOrEnd ? '-1px' : item.value < 10 ? "-3px" : '-6px',
            'align-items': startOrEnd ? "flex-start" : "center"
          }
        } else {
          return {
            'right': startOrEnd ? '-1px' : item.value < 10 ? "-3px" : '-6px',
            'align-items': startOrEnd ? "flex-end" : "center"
          }
        }
      }
    },

    scaleStyleLast() {
      if (!this.isOdd) {
        return {
          'right': '0px',
          'align-items': "flex-end",
          'white-space': 'nowrap'
        }
      } else {
        return {
          'left': `0px`,
          'align-items': "flex-start",
          'white-space': 'nowrap'
        }
      }
    }
  },
  mounted() {
    // this.setItemList()
  },
  methods: {
    // 获取无数据段
    getSchedule(item) {
      let MM = (stop) => {
        return stop.filter(date => {
          let Y = getDate(date).getFullYear()
          let M = getDate(date).getMonth() + 1
          return item.label === Y && item.value === M
        })
      }
      return this.stopDate.filter(stop => MM(stop).length > 0)
    },

    // 设置无数据段样式
    getScheduleStyle(schedule, item) {
      let y = this.getFullYear(schedule)
      let m = this.getMonth(schedule)
      let d = this.getDay(schedule)

      let style = {}
      // 同年-同月
      if (y[0] === y[1] && m[0] === m[1]) {
        let day = new Date(y[0], m[0], 0).getDate()
        style.width = Math.abs(this.width / day * (d[1] - d[0])).toFixed(2) + 'px'
        let name = !this.isOdd ? 'left' : 'right'
        style[name] = (this.width / day * d[0]).toFixed(2) + 'px'
        return style
      }

      // 同年-跨月
      if (y[0] === y[1] && m[0] < m[1]) {
        let day = new Date(y[0], m[0], 0).getDate()
        if (!this.isOdd) {
          if (item.value === m[0]) {
            style.width = Math.abs(this.width / day * (day - d[0])).toFixed(2) + 'px'
            style.left = this.width / day * d[0] + 'px'
          } else if (item.value === m[1]) {
            style.width = Math.abs(this.width / day * d[1]).toFixed(2) + 'px'
            style.left = '0px'
          }
        } else {
          if (item.value === m[0]) {
            style.width = Math.abs(this.width / day * (day - d[0])).toFixed(2) + 'px'
            style.right = this.width / day * d[0] + 'px'
          } else if (item.value === m[1]) {
            style.width = Math.abs(this.width / day * d[1]).toFixed(2) + 'px'
            style.right = '0px'
          }
        }
        return style
      }

      // 跨年
      if (y[0] !== y[1] && y[0] === item.label && m[0] === item.value) {
        let day = new Date(y[0], m[0], 0).getDate()
        style.width = Math.abs(this.width / day * (day - d[0])).toFixed(2) + 'px'
        style[!this.isOdd ? 'right' : 'left'] = '0px'
        return style
      }

      if (y[0] !== y[1] && y[1] === item.label && m[1] === item.value) {
        let day = new Date(y[1], m[1], 0).getDate()
        style.width = Math.abs((this.width / day).toFixed(2) * d[1]) + 'px'
        style[!this.isOdd ? 'left' : 'right'] = '0px'
        return style
      }
    },

    // item样式
    itemBoxStyle(item, index) {
      let style = {
        width: this.width + "px"
      }
      if (this.isStartM(index)) {
        style["border-top-left-radius"] = "50px"
        style["border-bottom-left-radius"] = "50px"
      }

      if (this.isEndM(index)) {
        if (this.isOdd) {
          style["border-top-left-radius"] = "50px"
          style["border-bottom-left-radius"] = "50px"
        } else {
          style["border-top-right-radius"] = "50px"
          style["border-bottom-right-radius"] = "50px"
        }
      }

      return style
    },

    // 获取中断时间数据: 20220315
    getStopDate(item) {
      return this.notDate.filter(not => {
        let Y = getDate(not).getFullYear()
        let M = getDate(not).getMonth() + 1
        return getVarType(not) !== 'array' && Y === item.label && M === item.value
      })
    },

    // 获取中断时间段数据：[20220315, 20220415]
    getStopDateArray(item) {
      let dates = []
      this.notDate.filter(i => getVarType(i) === 'array').map(date => {
        let YS = getDate(date[0]).getFullYear()
        let MS = getDate(date[0]).getMonth() + 1
        let DS = getDate(date[0]).getDate()

        let YE = getDate(date[1]).getFullYear()
        let ME = getDate(date[1]).getMonth() + 1
        let DE = getDate(date[1]).getDate()
        let days = new Date(item.label, item.value, 0).getDate()

        // 同年
        if (YS === item.label && YE === item.label) {
          // 同月
          if (MS === item.value && ME === item.value) {
            dates.push({start: DS, end: DE, range: DE - DS + 1})
          }
          // 跨月-头月
          else if (MS === item.value && ME > item.value) {
            dates.push({start: DS, end: days, range: days - DS + 1})
          }
          // 跨月-尾月
          else if (MS < item.value && ME === item.value) {
            dates.push({start: 1, end: DE, range: DE})
          }
          // 跨月-中月
          else if (MS < item.value && ME > item.value) {
            dates.push({start: 1, end: days, range: days})
          }
        }
        // 跨年 - 开始年
        else if (YS === item.label && YE !== item.label) {
          // 头月
          if (MS === item.value) {
            dates.push({start: DS, end: days, range: days - DS + 1})
          }
          // 中月
          else if (item.value > MS && item.value <= 12) {
            dates.push({start: 1, end: days, range: days})
          }
        }
        // 跨年 - 结束年
        else if (YS !== item.label && YE === item.label) {
          // 中月
          if (item.value >= 1 && item.value < ME) {
            dates.push({start: 1, end: days, range: days})
          }
          // 结尾月
          else if (item.value === ME) {
            dates.push({start: 1, end: DE, range: DS})
          }
        }
      })
      return dates
    },

    //获取中断时间数据集合
    getStopDateTips(item) {
      let tips = []

      // 不连续日期
      let ary = this.getStopDate(item)
      if (ary.length > 0) {
        let str = []
        ary.map(s => {
          let M = getDate(s).getMonth() + 1
          let D = getDate(s).getDate()

          if (str.length % 4 === 0) {
            str.push('<br/>' + M + '月' + D + "日")
          } else {
            str.push(M + '月' + D + "日")
          }
        })
        tips.push("余额不连续日期：" + str.join("，"))
      }

      // 不连续日期段
      let ary2 = this.getStopDateArray(item)
      if (ary2.length > 0) {
        let str = []
        ary2.map(s => {
          if (str.length % 2 === 0) {
            str.push(`<br/>${item.value}月${s.start}日-${item.value}月${s.end}日`)
          } else {
            str.push(`${item.value}月${s.start}日-${item.value}月${s.end}日`)
          }
        })
        tips.push("余额不连续时间段：" + str.join("，"))
      }

      return tips.join("<br/><br/>")
    },

    // 获取中断时间样式
    stopDateStyle(stop, stop_index) {
      let y = getDate(stop).getFullYear()
      let m = getDate(stop).getMonth() + 1
      let d = getDate(stop).getDate()
      let days = new Date(y, m, 0).getDate()
      let w = (this.width / days).toFixed(3)
      if (!this.isOdd) {
        return {
          width: w + "px",
          'align-items': 'flex-start',
          left: `${Math.abs(this.width / days * d - w).toFixed(3)}px`
        }
      } else {
        return {
          width: w + "px",
          'align-items': 'flex-end',
          right: `${Math.abs(this.width / days * d - w).toFixed(3)}px`
        }
      }
    },

    stopDateArrayStyle(item, stop) {
      let Y = item.label
      let M = item.value
      let days = new Date(Y, M, 0).getDate()
      let oneW = this.width / days
      let style = {}
      style.width = `${oneW * stop.range}px`

      if (!this.isOdd) {
        style.left = `${oneW * (stop.start - 1)}px`
      } else {
        style.right = `${oneW * (stop.start - 1)}px`
      }
      return style
    },

    // 获取隔断竖线样式
    getSortStyle() {
      let item = this.flowItem[this.flowItem.length - 1]
      let Color = this.getSortNotStyle(item) || this.getSortNotArrayStyle(item) ? '#F89F25' : '#1376FB'
      let style = {}
      if (this.isOdd) {
        style.left = '-10px'
      } else {
        style.right = '-10px'
      }
      return {
        ...style,
        backgroundColor: Color
      }
    },

    getSortNotArrayStyle(item) {
      let Y = item.label
      let M = item.value < 10 ? `0${item.value}` : item.value
      let days = new Date(Y, M, 0).getDate()
      let isColor = false
      let stopArr = this.getStopDateArray(item)

      // 获取次月第一天
      let nextMD = (md) => {
        let LY = getDate(md).getFullYear()
        let LM = getDate(md).getMonth() + 1
        return {label: LM === 12 ? LY + 1 : LY, value: LM === 12 ? 1 : LM + 1}
      }

      if (stopArr.length > 0) {
        let isLast = stopArr.find(s => s.end === days)
        let stopNextArr = this.getStopDateArray(nextMD(Y + "" + M + "" + days))
        let isNext = stopNextArr.find(s => s.start === 1)

        if(isLast && isNext){
          isColor = true
        }
      }

      return isColor
    },

    getSortNotStyle(item) {
      let Y = item.label
      let M = item.value
      let days = new Date(Y, M, 0).getDate()
      let isColor = false

      // 是否有某月最后一天
      let lastMD = this.notDate.find(not => {
        let NY = getDate(not).getFullYear()
        let NM = getDate(not).getMonth() + 1
        let ND = getDate(not).getDate()
        return NY === Y && M === NM && days === ND
      })

      // 获取次月第一天
      let nextMD = (md) => {
        let LY = getDate(md).getFullYear()
        let LM = getDate(md).getMonth() + 1
        let NY, NM;
        NY = LM === 12 ? LY + 1 : LY
        NM = LM === 12 ? 1 : LM + 1
        return {Y: NY, M: NM, D: 1}
      }

      if (lastMD) {
        // 是否有某月第一天
        let isNextMd = nextMD && this.notDate.find(not => {
          let NY = getDate(not).getFullYear()
          let NM = getDate(not).getMonth() + 1
          let ND = getDate(not).getDate()
          let lmd = nextMD(lastMD)
          return NY === lmd.Y && NM === lmd.M && ND === lmd.D
        })

        if (isNextMd) {
          isColor = true
        }
      }

      return isColor
    },

    // 开始时间和结束时间样式
    getStartStyle(item, name) {
      let Y = getDate(this[name]).getFullYear()
      let M = getDate(this[name]).getMonth() + 1
      let D = getDate(this[name]).getDate()
      let days = new Date(Y, M, 0).getDate()
      let style = {}
      let W = !this.isOdd ? this.width / days * D : this.width / days * (days - D)
      style.width = W.toFixed(2) + "px"
      style.left = "0px"
      return style
    },

    getEndStyle(item, name) {
      let Y = getDate(this[name]).getFullYear()
      let M = getDate(this[name]).getMonth() + 1
      let D = getDate(this[name]).getDate()
      let days = new Date(Y, M, 0).getDate()
      let style = {}
      let direction = this.isOdd ? 'left' : 'right'
      let W = this.width / days * (days - D)
      style.width = W.toFixed(2) + "px"
      style[direction] = "0px"

      if (this.isOdd) {
        style["border-top-left-radius"] = "50px"
        style["border-bottom-left-radius"] = "50px"
      } else {
        style["border-top-right-radius"] = "50px"
        style["border-bottom-right-radius"] = "50px"
      }

      return style
    },

    getEndTxtStyle(item) {
      if (this.isOdd) {
        return {right: "0px"}
      } else {
        return {left: "0px", textAlign: 'left'}
      }
    },

    getEndDate(item) {
      if (item.value < 12) {
        return `${item.label}年${item.value + 1}月`
      } else {
        return `${item.label + 1}年1月`
      }
    },

    getFullYear(dates) {
      return dates.map(date => {
        return getFullYear(date)
      })
    },

    getMonth(dates) {
      return dates.map(date => {
        return getMonth(date)
      })
    },

    getDay(dates) {
      return dates.map(date => {
        return getDay(date)
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.ed-flow-item {
  position: relative;

  .ed-flow-item--list {
    display: flex;

    .flow-item-box--hover {
      transition: transform .2s;

      &:hover {
        transform: scale(1, 1.4);
      }
    }

    .flow-item-box {
      position: relative;
      height: 10px;
      background-color: #1376FB;


      .ed-flow-item--stop {
        width: 100%;
        height: 10px;
        display: flex;
        position: absolute;
        top: 0;
        z-index: 20;
        transition: transform .2s;

        &:hover {
          transform: scale(1, 1.4);
          background-color: #EFEFEF;
        }

        .item--stop-vertical {
          position: absolute;
          background: #F89F25;
          height: 100%;
        }
      }

      .ed-flow-item--schedule {
        background: #EFEFEF;
        height: 10px;
        position: absolute;
        z-index: 10;
      }

      .item-start-date {
        font-size: 12px;
        text-align: right;
        line-height: 10px;
        background: #EFEFEF;
        height: 10px;
        position: absolute;
        z-index: 10;
        margin-left: -1px;
        padding-right: 1px;
        border-top-left-radius: 8px;
        border-bottom-left-radius: 8px;

        .item-start-date--text {
          display: block;
          position: absolute;
          top: -18px;
          right: -25px;
          white-space: nowrap;
        }
      }

      .item-end-date {
        background: #EFEFEF;
        height: 10px;
        position: absolute;
        z-index: 10;
        font-size: 12px;
        text-align: right;
        line-height: 10px;

        .item-start-date--text {
          display: block;
          position: absolute;
          top: -18px;
          right: -25px;
          white-space: nowrap;
        }
      }

      .ed-flow-item--scale {
        position: absolute;
        top: 10px;
        font-size: 12px;
        z-index: 10;
        width: auto;
        display: flex;
        flex-direction: column;
        align-items: center;
      }

      .ed-flow-item--scale-last {
        position: absolute;
        top: 10px;
        left: 0;
        font-size: 12px;
        z-index: 10;
        width: auto;
        display: flex;
        flex-direction: column;
        align-items: center;
      }
    }

  }

  .ed-flow-item--sort {
    position: absolute;
    width: 10px;
    height: 80px;
    top: 0px;
    background-color: #1376FB;
  }
}

.ed-flow-item--schedule-oddEnd {
  border-top-right-radius: 50px;
  border-bottom-right-radius: 50px;
  margin-right: -1px;
}

.ed-flow-item--schedule-evenEnd {
  border-top-left-radius: 50px;
  border-bottom-left-radius: 50px;
  padding-left: 1px;
}
</style>
<style>
.ed-flow-item--popper {
  z-index: 3000 !important;
}
</style>
