const WEEK = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
const toHideToast = debounce(options => {
  wx.showToast(options)
}, 400)

function platform() {
  let systemInfo = {}
  let u = ''
  wx.getSystemInfo({
    success(res) {
      systemInfo = res
      u = systemInfo.system || ''
    }
  })

  return {
    ...systemInfo,
    ios: u.indexOf('iOS') > -1, // ios终端
    android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1 // android终端或uc浏览器
  }
}

function addMultiMonth(dtstr, n) {
  let yy = parseInt(dtstr[0])
  let mm = parseInt(dtstr[1])
  let dd = parseInt(dtstr[2])
  const dt = new Date(yy, mm, dd)

  const num = dt.getMonth() + parseInt(n)
  if (num / 12 > 1) {
    yy += Math.floor(num / 12)
    mm = num % 12
  } else {
    mm += parseInt(n)
  }

  return [yy, mm, dd]
}

function range(n, m, polyfill = false, unit = '') {
  const arr = []
  for (let i = n; i <= m; i++) {
    const value = (polyfill && i < 10 ? '0' + i : i) + unit
    arr.push({
      text: value,
      value: i
    })
  }
  return arr
}

function glDate() {
  const date = new Date()
  const YEAR = date.getFullYear()
  const MONTH = date.getMonth() + 1
  const DAY = date.getDate()
  const min = [YEAR, MONTH, DAY]
  // 产品要求：可选时间范围未来3个月内
  const max = addMultiMonth(min, 3)
  const data = range(min[0], max[0], false, '')
  data.forEach(year => {
    const minMonth = year.value === min[0] ? min[1] : 1
    const maxMonth = year.value === max[0] ? max[1] : 12
    year.children = range(minMonth, maxMonth, true, '')
    year.children.forEach(month => {
      let day = 30
      if ([1, 3, 5, 7, 8, 10, 12].indexOf(month.value) > -1) {
        day = 31
      } else {
        if (month.value === 2) {
          day = !(year.value % 400) || (!(year.value % 4) && year.value % 100) ? 29 : 28
        }
      }
      const minDay = year.value === min[0] && month.value === min[1] ? min[2] : 1
      const maxDay = year.value === max[0] && month.value === max[1] ? max[2] : day
      month.children = range(minDay, maxDay, true, '')
    })
  })
  return data
}

function formatGlDate() {
  const MINUTES = ['00', '10', '20', '30', '40', '50']
  const arr = glDate()
  const result = []
  for (let i = 0; i < arr.length; i++) {
    const YYYY = arr[i].text
    for (let j = 0; j < arr[i].children.length; j++) {
      const MM = arr[i].children[j].text
      for (let k = 0; k < arr[i].children[j].children.length; k++) {
        const DD = arr[i].children[j].children[k].text
        result.push(`${YYYY}-${MM}-${DD}`)
      }
    }
  }

  const one = result.map((item, index) => {
    const cur = new Date(platform().ios ? item.replace(/-/g, '/') : item).getDay()
    const value = item.replace('-', '年').replace('-', '月') + '日' + ' ' + WEEK[cur]
    return {
      value: (index + 11).toString(),
      text: value.replace(/(.*年)(.*)/, '$2'),
      _text: value.replace(/日.*/, '').replace(/年|月/g, '-')
    }
  })

  const two = range(0, 23, true, '').map((item, index) => {
    return {
      value: '11' + (index < 10 ? '0' + index : index),
      text: item.text + '时',
      _text: item.text
    }
  })

  const three = MINUTES.map((item, index) => {
    return {
      value: '1100' + (index < 10 ? '0' + index : index),
      text: item + '分',
      _text: item
    }
  })

  return {
    one,
    two,
    three
  }
}

const formatTime = date => {
  const year = date.getFullYear()
  const month = date.getMonth() + 1
  const day = date.getDate()
  const hour = date.getHours()
  const minute = date.getMinutes()
  const second = date.getSeconds()

  return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(
    formatNumber).join(':')}`
}

const formatArr = (arr) => {
  while (arr.some(item => Array.isArray(item))) {
    arr = [].concat(...arr)
  }
  return arr
}

function formatNumber(n) {
  n = n.toString()
  return n[1] ? n : `0${n}`
}

function cutDownTime(ts = 0, type) {
  if (ts < 0) {
    return ['0', '00', '00', '00']
  }
  ts = parseInt(ts)
  var D = Math.floor(ts / 24 / 60 / 60)

  // 小时位
  var h = Math.floor((ts - D * 24 * 60 * 60) / 3600)
  // 分钟位
  var m = Math.floor((ts - D * 24 * 3600 - h * 3600) / 60)
  // 秒位
  var s = ts - D * 24 * 3600 - h * 3600 - m * 60
  if (['hh:mm:ss'].includes(type)) {
    return `${formatNumber(D * 24 + h)}:${formatNumber(m)}:${formatNumber(s)}`
  }

  if (type === 'hh:mm zh') {
    return (D * 24 + h) + '小时' + m + '分'
  }

  return [D, formatNumber(h), formatNumber(m), formatNumber(s)]
}

function formatLocation(longitude, latitude) {
  if (typeof longitude === 'string' && typeof latitude === 'string') {
    longitude = parseFloat(longitude)
    latitude = parseFloat(latitude)
  }

  longitude = longitude.toFixed(2)
  latitude = latitude.toFixed(2)

  return {
    longitude: longitude.toString().split('.'),
    latitude: latitude.toString().split('.')
  }
}

function formatTs(ts) {
  const date = new Date(ts)

  return {
    YYYY: date.getFullYear(),
    MM: datePolyfill(date.getMonth() + 1),
    DD: datePolyfill(date.getDate()),
    HH: datePolyfill(date.getHours()),
    mm: datePolyfill(date.getMinutes()),
    ss: datePolyfill(date.getSeconds()),
    week: WEEK[date.getDay()]
  }
}

function datePolyfill(val) {
  return (val < 10 ? '0' + val : val) + ''
}

/**
 * 检测当前的小程序
 * 是否是最新版本，是否需要下载、更新
 */
function checkUpdateVersion() {
  //判断微信版本是否 兼容小程序更新机制API的使用
  if (wx.canIUse('getUpdateManager')) {
    const updateManager = wx.getUpdateManager()
    //检测版本更新
    updateManager.onCheckForUpdate(function (res) {
      if (res.hasUpdate) {
        updateManager.onUpdateReady(function () {
          wx.showModal({
            title: '温馨提示',
            content: '检测到新版本，是否重启小程序？',
            showCancel: false,
            success: function (res) {
              if (res.confirm) {
                // 新的版本已经下载好，调用 applyUpdate 应用新版本并重启
                updateManager.applyUpdate()
              }
            }
          })
        })
        updateManager.onUpdateFailed(function () {
          // 新版本下载失败
          wx.showModal({
            title: '已有新版本',
            content: '请您删除小程序，重新搜索进入'
          })
        })
      }
    })
  } else {
    wx.showModal({
      title: '溫馨提示',
      content: '当前微信版本过低，无法使用该功能，请升级到最新微信版本后重试。'
    })
  }
}

/**
 * 函数防抖
 * @param fn
 * @param wait
 * @param immediate
 * @returns {(function(...[*]=): void)|*}
 */
function debounce(fn, wait = 1000, immediate = false) {
  let timer = null
  return function (...args) {
    const context = this
    if (timer) {
      clearTimeout(timer)
    }
    if (immediate && !timer) {
      fn.apply(context, args)
    }

    timer = setTimeout(() => {
      fn.apply(context, args)
    }, wait)
  }
}

function fen2Yuan(num) {
  return isNaN(num) ? '' : (num * 0.01).toFixed(2) * 1
}

function yuan2Fen(num) {
  if (isNaN(num)) {
    return ''
  }
  var amount = num.toString()
  var index = amount.indexOf('.')
  var arr = amount.split('.')
  var result = arr[0] * 100
  if (index > -1) {
    var temp = arr[1].split('')
    for (var i = 0; i < temp.length; i++) {
      if (i === 0) {
        result += temp[i] * 10
      } else {
        result += temp[i] * 1
      }
    }
  }
  return result
}

/**
 * 开始时间与耗时之间的日期详情
 * @param startTs
 * @param duration
 * @returns {[]|*[]}
 */
function getDayList(startTs, duration) {
  const isStartTs = Object.prototype.toString.call(startTs) === '[object Number]'
  const isDuration = Object.prototype.toString.call(duration) === '[object Number]'
  if (!isStartTs || !isDuration) {
    return []
  }
  const result = []
  const hours = []
  const restTs = 3 * 3600 * 1000
  const start = formatTs(startTs)
  const startHour = start.HH * 1
  const polyfill = platform().ios ? '/' : '-'
  const YYYYMMDD = `${start.YYYY}${polyfill}${start.MM}${polyfill}${start.DD}`
  const startMax = new Date(`${YYYYMMDD} 23:59:59`).getTime()
  // 当天结束时间
  let endTs = startTs + duration
  // 当天结束时间
  let end = formatTs(endTs)
  let endHour = end.HH * 1

  // 大于当天23:59:59时
  if (endTs > startMax) {
    endTs = startMax
    end = formatTs(startMax)
    endHour = end.HH * 1
    // 计算剩余日期
    duration = duration - (startMax - startTs)
  } else {
    // 小于等于当天23:59:59时
    duration = 0
  }

  for (let i = startHour; i <= endHour; i++) {
    hours.push(i)
  }

  // 限行：高速2:00~5:00客车禁止通行
  if (hours.some(item => [2, 3, 4].findIndex(hour => hour === item) > -1)) {
    if (duration > 0) {
      duration += restTs
    } else {
      if (restTs + endTs <= startMax) {
        endTs = restTs + endTs
        end = formatTs(endTs)
      } else {
        duration = restTs - (startMax - endTs)
        end = formatTs(startMax)
        endTs = startMax
      }
    }
  }

  // 相差一分钟以上
  if (endTs - startTs >= 60000) {
    result.push({
      start,
      end,
      startTs,
      endTs,
      morThen22: endHour >= 22, // 关联住宿：是否跨过当天22:00
      duration
    })
  }

  if (duration <= 0) {
    return result
  }

  return result.concat(getDayList(endTs + 1000, duration - 1000))
}

module.exports = {
  platform,
  formatTime,
  formatArr,
  formatGlDate,
  cutDownTime,
  formatLocation,
  formatTs,
  checkUpdateVersion,
  debounce,
  toHideToast,
  fen2Yuan,
  yuan2Fen,
  getDayList
}
