import { TimeInfo } from '../../utils/time'
interface Options<T> {
  hourList: any[]
  minuteList: any[]
  secondsList: any[]
  timeList: any[]
  valueFormatArr: any[]
  showHour: boolean
  showMinute: boolean
  isShowTimeType: boolean
  combination: boolean
  interval: string
  hourType: number
}
class TimePicker<T> {
  private hourList: any[]
  private minuteList: any[]
  private secondsList: any[]
  private timeList: any[]
  private valueFormatArr: any[]
  private showHour: boolean
  private showMinute: boolean
  private isShowTimeType: boolean
  private combination: boolean
  private interval: string
  private hourType: number
  private timeInfo: any
  private disabledTimeData: object
  private timeTypeIndexList: Array<number>
  private timeType: Array<string>

  constructor(options: Options<T>) {
    this.hourList = options.hourList
    this.minuteList = options.minuteList
    this.secondsList = options.secondsList
    this.timeList = options.timeList
    this.valueFormatArr = options.valueFormatArr
    this.showHour = options.showHour
    this.showMinute = options.showMinute
    this.isShowTimeType = options.isShowTimeType
    this.combination = options.combination
    this.interval = options.interval
    this.hourType = options.hourType
    this.timeTypeIndexList = [0, 1]
    this.timeType = ['AM', 'PM']
    this.init()
  }
  init() {
    const hourDuration = this.hourType === 12 && !this.combination ? '0-11' : '0-23'
    const intervalArr = this.interval.split(':')
    const interval = +intervalArr[0] * 60 + +intervalArr[1] || 0
    const options = {
      hourType: this.hourType,
      hourDuration: hourDuration,
      minuteDuration: '0-59',
      secondDuration: '0-59',
      interval: interval
    }
    this.timeInfo = new TimeInfo(options)
    this.hourList = this.timeInfo.hours
    this.minuteList = this.timeInfo.minutes
    this.secondsList = this.timeInfo.seconds
    this.timeList = this.timeInfo.timeList
  }
  timeTypeIndexListInit(range) {
    const timeTypeIndexList = []
    range.map(item => {
      const itemArr = item.split('-')
      const startTime = this.translateRangeTime(itemArr[0] || '')
      const endTime = this.translateRangeTime(itemArr[1] || '')
      if (this.isShowTimeType && timeTypeIndexList.length < 2) {
        if (timeTypeIndexList.indexOf(startTime['timeTypeIndex']) === -1) {
          timeTypeIndexList.push(startTime['timeTypeIndex'])
        }
        if (timeTypeIndexList.indexOf(endTime['timeTypeIndex']) === -1) {
          timeTypeIndexList.push(endTime['timeTypeIndex'])
        }
      }
      this.timeTypeIndexList = timeTypeIndexList
    })
  }
  getNowInfo() {
    return this.timeInfo.getNowInfo()
  }
  translateRangeTime(time) {
    if (time === '' || time === undefined) {
      return {
        time: ''
      }
    }
    const timeArr = time.split(':')
    const timeObject = {}
    if (this.hourType === 12) {
      timeObject['TfHour'] = timeArr[0]
      timeObject['timeTypeIndex'] = +timeArr[0] >= 12 ? 1 : 0
    }
    timeArr[0] = this.isShowTimeType && +timeArr[0] > 12 ? +timeArr[0] - 12 : timeArr[0]
    timeObject['time'] = timeArr.join(':')
    timeObject['hour'] = this.showHour || this.combination ? timeArr[0] : ''
    timeObject['hour'] = +timeObject['hour'] === 12 && this.hourType === 12 ? '00' : timeObject['hour']
    let second = ''
    if (timeArr.length <= this.valueFormatArr.length) {
      if (!this.showHour && !this.showMinute) {
        second = timeArr[0]
      } else if (!this.showHour && this.showMinute) {
        second = timeArr[1]
      } else {
        second = timeArr[2]
      }
    } else {
      second = timeArr[2]
    }
    timeObject['minute'] =
      this.showHour || (!this.showHour && timeArr.length === 3) || this.combination ? timeArr[1] : timeArr[0]
    timeObject['second'] = second
    return timeObject
  }

  getHourRangeList(range, timeTypeIndex) {
    let hours = []
    range.map(item => {
      const itemArr = item.split('-')
      const startTime = this.translateRangeTime(itemArr[0] || '')
      let endTime = this.translateRangeTime(itemArr[1] || '')
      endTime = endTime['time'] === '' ? startTime : endTime
      if (this.isShowTimeType) {
        if (startTime['timeTypeIndex'] === endTime['timeTypeIndex'] && startTime['timeTypeIndex'] === timeTypeIndex) {
          for (let i = +startTime['hour']; i <= +endTime['hour']; i++) {
            hours.push(timeDataHandle(i))
          }
        }
        if (startTime['timeTypeIndex'] !== endTime['timeTypeIndex']) {
          if (timeTypeIndex === startTime['timeTypeIndex']) {
            for (let i = +startTime['hour']; i <= 12; i++) {
              hours.push(timeDataHandle(i))
            }
          } else {
            for (let i = 0; i <= endTime['hour']; i++) {
              hours.push(timeDataHandle(i))
            }
          }
        }
      } else {
        for (let i = +startTime['hour']; i <= +endTime['hour']; i++) {
          hours.push(timeDataHandle(i))
        }
      }
    })
    hours = hours.length === 0 ? this.hourList : hours
    return hours
  }

  getMinuteRangeList = (range, hour, timeTypeIndex) => {
    let minutes = []
    range.map(item => {
      const itemArr = item.split('-')
      const startTime = this.translateRangeTime(itemArr[0] || '')
      let endTime = this.translateRangeTime(itemArr[1] || '')
      endTime = endTime['time'] === '' ? startTime : endTime
      let startMinute = +startTime['minute'] || 0
      let endMinute = +endTime['minute'] || 59
      if (!this.showHour) {
        const start = Math.min(startMinute, endMinute)
        const end = Math.max(startMinute, endMinute)
        startMinute = start
        endMinute = end
      }
      if (this.hourType === 12 && startTime['timeTypeIndex'] !== endTime['timeTypeIndex']) {
        if (+startTime['hour'] === +hour && startTime['timeTypeIndex'] === timeTypeIndex) {
          for (let i = startMinute; i <= 59; i++) {
            minutes.push(timeDataHandle(i))
          }
        } else if (+endTime['hour'] === +hour && endTime['timeTypeIndex'] === timeTypeIndex) {
          for (let i = 0; i <= endMinute; i++) {
            minutes.push(timeDataHandle(i))
          }
        }
      } else {
        const start = (this.hourType === 12 && startTime['timeTypeIndex'] === timeTypeIndex) || this.hourType === 24
        const end = (this.hourType === 12 && endTime['timeTypeIndex'] === timeTypeIndex) || this.hourType === 24
        if (+startTime['hour'] === +hour && +endTime['hour'] !== +hour && start) {
          for (let i = startMinute; i <= 59; i++) {
            minutes.push(timeDataHandle(i))
          }
        } else if (+startTime['hour'] !== +hour && +endTime['hour'] === +hour && end) {
          for (let i = 0; i <= endMinute; i++) {
            minutes.push(timeDataHandle(i))
          }
        } else if (+startTime['hour'] === +hour && +endTime['hour'] === +hour) {
          for (let i = startMinute; i <= endMinute; i++) {
            minutes.push(timeDataHandle(i))
          }
        }
        if (!this.showHour) {
          minutes = minutes[minutes.length - 1] > endMinute ? [] : minutes
          for (let i = startMinute; i <= endMinute; i++) {
            minutes.push(timeDataHandle(i))
          }
        }
      }
    })
    minutes = minutes.length === 0 ? this.minuteList : minutes
    return minutes
  }
  getSecondRangeList(range, hour, minute) {
    let seconds = []
    range.map(item => {
      const itemArr = item.split('-')
      const startTime = this.translateRangeTime(itemArr[0] || '')
      let endTime = this.translateRangeTime(itemArr[1] || '')
      endTime = endTime['time'] === '' ? startTime : endTime
      let startSecond = +startTime['second'] || 0
      let endSecond = +endTime['second'] || 59
      if ((+startTime['hour'] === +hour || !this.showHour) && +startTime['minute'] === +minute) {
        for (let i = startSecond; i <= 59; i++) {
          seconds.push(timeDataHandle(i))
        }
      } else if ((+endTime['hour'] === +hour || !this.showHour) && +endTime['minute'] === +minute) {
        for (let i = 0; i <= endSecond; i++) {
          seconds.push(timeDataHandle(i))
        }
      }
      if (!this.showHour && !this.showMinute) {
        const start = Math.min(startSecond, endSecond)
        const end = Math.max(startSecond, endSecond)
        startSecond = start
        endSecond = end
        seconds = seconds[seconds.length - 1] > endSecond ? [] : seconds
        for (let i = startSecond; i <= endSecond; i++) {
          seconds.push(timeDataHandle(i))
        }
      }
    })
    seconds = seconds.length === 0 ? this.secondsList : seconds
    return seconds
  }
  getTimeRangeList(timeList, range) {
    let list = []
    const date = new Date()
    timeList.map(timeItem => {
      const timeArr = timeItem.split(':')
      const time = date.setHours(+timeArr[0], +timeArr[1], 0)
      range.some(item => {
        const itemArr = item.split('-')
        const startTime = this.translateRangeTime(itemArr[0] || '')
        let endTime = this.translateRangeTime(itemArr[1] || '')
        endTime = endTime['time'] === '' ? startTime : endTime
        var start = date.setHours(+startTime['hour'] || 0, +startTime['minute'] || 0, +startTime['second'] || 0)
        var end = date.setHours(+endTime['hour'] || 0, +endTime['minute'] || 0, +endTime['second'] || 0)
        if (time >= start && time <= end) {
          list.push(timeItem)
          return true
        }
      })
    })
    list = range.length === 0 ? this.timeList : list
    return list
  }
  getIndex() {
    const hourIndex = this.hourType === 24 ? this.valueFormatArr.indexOf('HH') : this.valueFormatArr.indexOf('hh')
    const minuteIndex = this.valueFormatArr.indexOf('mm')
    const secondsIndex = this.valueFormatArr.indexOf('ss')
    return {
      hourIndex: hourIndex,
      minuteIndex: minuteIndex,
      secondsIndex: secondsIndex
    }
  }
  toCheck(TimepickerBox, isSelectRange, activeFlag, flag) {
    let domArr = TimepickerBox.querySelectorAll('.lu-timepicker-active')
    if (!isSelectRange || !activeFlag) {
      domArr = TimepickerBox.querySelectorAll('.lu-timepicker-unrange')
    }
    for (var i = 0; i < domArr.length; i++) {
      const parent = this.combination ? domArr[i].parentNode : domArr[i].parentNode.parentNode
      const scrollTop = domArr[i].offsetTop - parent.offsetTop - (parent.clientHeight - domArr[i].clientHeight) / 2
      if (flag) {
        parent.scrollTo({
          top: scrollTop,
          behavior: 'smooth'
        })
      } else {
        parent.scrollTop = scrollTop
      }
    }
  }
  format(time, typeIndex, range) {
    let timeTypeIndex = typeIndex
    this.timeTypeIndexListInit(range)
    if (time === '')
      return {
        timeObject: { time: time, timeTf: time },
        timeTypeIndex: timeTypeIndex
      }
    let timeInfoArr = time.split(':')
    let hour = ''
    let timeHour = ''
    const hourIndex = this.hourType === 24 ? this.valueFormatArr.indexOf('HH') : this.valueFormatArr.indexOf('hh')
    timeInfoArr = timeInfoArr.map(item => {
      item = timeDataHandle(item)
      return item
    })
    if (this.combination) {
      time = timeInfoArr.join(':')
    }
    if (this.showHour) {
      timeHour = timeInfoArr[hourIndex]
      hour = this.hourType === 12 && +timeHour > 12 ? timeDataHandle(+timeHour - 12) : timeDataHandle(timeHour)
    }
    timeInfoArr[hourIndex] = hour
    timeInfoArr[hourIndex] = this.hourType === 12 && +timeInfoArr[hourIndex] === 0 ? 12 : timeInfoArr[hourIndex]
    const timeFormat = timeInfoArr.join(':')
    const timeObject = {
      time: timeFormat,
      hourType: this.hourType
    }
    if (this.hourType === 12) {
      timeObject['timeType'] = +timeHour >= 12 ? 'PM' : 'AM'
      timeTypeIndex = +timeHour >= 12 ? 1 : 0
      timeTypeIndex = this.timeTypeIndexList.length === 1 ? this.timeTypeIndexList[0] : timeTypeIndex
      timeObject['timeTf'] = twToTf(timeFormat, timeTypeIndex)
    }
    return {
      timeObject: timeObject,
      timeTypeIndex: timeTypeIndex
    }
  }
  handleCompare(options) {
    if (this.combination) {
      return options.disabledType === 'pre'
        ? timeStamp(options.disabledTimeData) < timeStamp(options.time)
        : timeStamp(options.disabledTimeData) > timeStamp(options.time)
    }
    const isNoSame = options.disabledTimeData.timeTypeIndex !== options.timeTypeIndex
    if (this.isShowTimeType && isNoSame) return false
    switch (options.type) {
      case 'hour': {
        const hourCompare =
          options.disabledType === 'pre'
            ? +options.disabledTimeData.hour < +options.time
            : +options.disabledTimeData.hour > +options.time
        const hour = +this.hourList[options.hourIndex]
        if (this.isShowTimeType && options.disabledType === 'pre' && +options.disabledTimeData.hour < +hour) {
          options.handleClick('hourIndex', this.hourList.indexOf(options.disabledTimeData.hour))
        }
        return hourCompare
      }
      case 'minutes': {
        const isHour = +options.disabledTimeData.hour === +this.hourList[options.hourIndex]
        const minutes = +this.minuteList[options.minuteIndex]
        if (isHour && options.disabledType === 'pre' && +options.disabledTimeData.minutes < +minutes) {
          options.handleClick('minuteIndex', this.minuteList.indexOf(options.disabledTimeData.minutes))
        }
        const minuteCompare =
          options.disabledType === 'pre'
            ? (isHour || !this.showHour) && +options.disabledTimeData.minutes < +options.time
            : (isHour || !this.showHour) && +options.disabledTimeData.minutes > +options.time
        return minuteCompare
      }
      case 'seconds': {
        const isHour = +options.disabledTimeData.hour === +this.hourList[options.hourIndex]
        const isMinute = +options.disabledTimeData.minutes === +this.minuteList[options.minuteIndex]
        const seconds = +this.secondsList[options.secondsIndex]
        const isEqual = (isHour && isMinute) || (isHour && !this.showMinute) || (isMinute && !this.showHour)
        if (isEqual && options.disabledType === 'pre' && +options.disabledTimeData.seconds < +seconds) {
          options.handleClick('secondsIndex', this.secondsList.indexOf(options.disabledTimeData.seconds))
        }
        const secondsCompare =
          options.disabledType === 'pre'
            ? isEqual && +options.disabledTimeData.seconds < +options.time
            : isEqual && +options.disabledTimeData.seconds > +options.time
        return secondsCompare
      }
    }
  }
  handleDisabled(disabledTime, disabledType, timeTypeIndex) {
    if (JSON.stringify(disabledTime) === '{}') return
    const { hourIndex, minuteIndex, secondsIndex } = this.getIndex()
    const time = disabledTime.time
    if (this.combination) {
      this.disabledTimeData = time
    } else {
      const disabledTimeArr = time.split(':')
      this.disabledTimeData = {
        hour: disabledTimeArr[hourIndex] || 0,
        minutes: disabledTimeArr[minuteIndex] || 0,
        seconds: disabledTimeArr[secondsIndex] || 0,
        timeTypeIndex: disabledTime.timeType === 'AM' ? 0 : 1
      }
      this.disabledTimeData['hour'] = +this.disabledTimeData['hour'] === 12 ? 0 : this.disabledTimeData['hour']
      if (disabledType === 'pre') {
        this.timeTypeIndexList = this.disabledTimeData['timeTypeIndex'] === 0 ? [0] : [1, 0]
      } else {
        this.timeTypeIndexList = this.disabledTimeData['timeTypeIndex'] === 1 ? [1] : [1, 0]
      }
    }
  }

  compareSelectRange(hour, minute, second, range) {
    let isSelectRange = false
    range.map(item => {
      const itemArr = item.split('-')
      const startTime = this.translateRangeTime(itemArr[0] || '')
      const endTime = this.translateRangeTime(itemArr[1] || '')
      var date = new Date()
      if (this.isShowTimeType) {
        startTime['hour'] = startTime['TfHour']
        endTime['hour'] = endTime['TfHour']
      }
      if (!this.combination) {
        hour = this.showHour ? hour : startTime['hour']
        minute = !this.showHour && !this.showMinute ? startTime['minute'] : minute
        endTime['hour'] = this.showHour ? endTime['hour'] : startTime['hour']
        endTime['minute'] = !this.showHour && !this.showMinute ? startTime['minute'] : endTime['minute']
      }
      var time = date.setHours(+hour || 0, +minute || 0, +second || 0)
      var start = date.setHours(+startTime['hour'] || 0, +startTime['minute'] || 0, +startTime['second'] || 0)
      var end = date.setHours(+endTime['hour'] || 0, +endTime['minute'] || 0, +endTime['second'] || 0)
      if (time >= start && time <= end) {
        isSelectRange = true
      }
    })
    return isSelectRange
  }
  getHour(hour) {
    const tHour = this.hourType === 12 && +hour > 12 ? +hour - 12 + '' : hour
    return tHour
  }
  getTimeArr(hour, minute, second) {
    const timeArr = []
    this.valueFormatArr.map((item, index) => {
      if (item === 'HH' || item === 'hh') {
        timeArr[index] = hour
      } else if (item === 'mm') {
        timeArr[index] = minute
      } else if (item === 'ss' && !this.combination) {
        timeArr[index] = second
      }
    })
    return timeArr
  }
  getTimeObject(timeArr, timeTypeIndex) {
    timeArr[0] = this.isShowTimeType && +timeArr[0] === 0 ? 12 : timeArr[0]
    const time = timeArr.join(':')
    const timeObject = {
      time: time,
      hourType: this.hourType
    }
    if (this.isShowTimeType) {
      timeObject['timeType'] = this.timeType[timeTypeIndex]
      timeObject['timeTf'] = twToTf(time, timeTypeIndex)
    }
    return timeObject
  }

  timeHandle(options) {
    const object = {}
    const { hourIndex } = this.getIndex()
    if (options.nowFlag) {
      let timeArr = []
      timeArr = this.getTimeArr(this.getHour(options.timeInfoArr[0]), options.timeInfoArr[1], options.timeInfoArr[2])
      options.disabledTime = {
        ...options.disabledTime,
        time: timeArr.join(':')
      }
    }
    if (this.showHour) {
      const timeHour = options.nowInfo ? options.timeInfoArr[0] : options.timeInfoArr[hourIndex]
      const hour = this.getHour(timeHour)
      object['hour'] = hour
      let timeTypeIndex = 0
      if (this.hourType === 12) {
        timeTypeIndex = +timeHour >= 12 ? 1 : 0
      }
      object['timeTypeIndex'] = timeTypeIndex
      if (options.nowFlag) {
        options.disabledTime['timeType'] = this.timeType[timeTypeIndex]
      }
    }
    object['disabledTime'] = options.disabledTime
    if (this.combination) {
      const timeIndexInit = options.timeIndex
      options.timeIndex = this.timeList.findIndex(item => {
        return item === options.timeInfoArr[0] + ':' + options.timeInfoArr[1]
      })
      if (options.timeIndex !== -1) {
        options.timeObject.timeIndex = options.timeIndex
      }
      object['timeObject'] = options.timeObject
      const timeIndex = options.timeIndex
      object['timeIndex'] = options.isSelectRange && timeIndex === -1 ? timeIndexInit : options.timeIndex
      object['isSelectRange'] = options.isSelectRange && timeIndex === -1 ? false : options.isSelectRange
      object['activeFlag'] = options.timeObject.timeIndex
    }
    return object
  }
}
const timeDataHandle = time => {
  return +time < 10 ? '0' + +time : time + ''
}
const twToTf = (time, timeTypeIndex) => {
  const timeArr = time.split(':')
  timeArr[0] =
    (timeTypeIndex === 0 && +timeArr[0] !== 0) || (timeTypeIndex === 1 && +timeArr[0] === 12)
      ? timeArr[0]
      : +timeArr[0] + 12 + ''
  timeArr[0] = timeTypeIndex === 0 && +timeArr[0] === 12 ? '00' : timeArr[0]
  return timeArr.join(':')
}
const inputFormat = (val, hourType) => {
  if (hourType === 24 || val.time === '') return val.time
  const str = val.timeType + ' ' + val.time
  return str
}
const timeStamp = time => {
  const timeArr = time.split(':')
  return Number(+timeArr[0] * 3600) + Number(+timeArr[1] * 60)
}
export { TimePicker, timeDataHandle, twToTf, inputFormat }
