import Big from 'big.js'
/**
 * @description 是否被定义
 * @param {any} val
 * @returns {Boolean}
 */

export function isDefine(val: any) {
  return val !== void 0 && val !== null
}

/**
 * @description 类型判断
 * @param {any} data
 * @returns {String}
 */
export function typeOf(data: any) {
  return Object.prototype.toString
    .call(data)
    .match(/\[object\s+(.*)\]/)?.[1]
    ?.toLocaleLowerCase()
}

/**
 * @description 对象空属性(undefined | null)过滤
 * @param  {Object} data 过滤对象
 * @returns {Object}
 */
export function filterEmpty(data: Record<string, unknown>) {
  if (typeOf(data) === 'object') {
    data = Object.entries(data).reduce<Record<string, unknown>>((d, [k, v]) => {
      if (isDefine(v)) {
        d[k] = v
      }
      return d
    }, {})
  }
  return data
}

/**
 * @description 数字转中文
 * @param {Number} number
 * @return {string}
 */

export const numberToChinese = (num: number) => {
  const DICT = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十']
  const UNIT = ['', '十', '百', '仟', '萬', '億', '点', '']
  const a = ('' + num).replace(/(^0*)/g, '').split('.')
  let k = 0
  let re = ''

  for (let i = a[0].length - 1; i >= 0; i--) {
    switch (k) {
      case 0:
        re = UNIT[7] + re
        break
      case 4:
        if (!new RegExp('0{4}//d{' + (a[0].length - i - 1) + '}$').test(a[0])) re = UNIT[4] + re
        break
      case 8:
        re = UNIT[5] + re
        UNIT[7] = UNIT[5]
        k = 0
        break
    }
    if (k % 4 == 2 && a[0].charAt(i + 2) !== '0' && a[0].charAt(i + 1) === '0') re = DICT[0] + re
    if (a[0].charAt(i) !== '0') re = DICT[+a[0].charAt(i)] + UNIT[k % 4] + re
    k++
  }
  if (a.length > 1) {
    // 加上小数部分(如果有小数部分)
    re += UNIT[6]
    for (let i = 0; i < a[1].length; i++) re += DICT[+a[1].charAt(i)]
  }
  if (re == '一十') re = '十'
  if (re.match(/^一/) && re.length == 3) re = re.replace('一', '')
  return re
}

/**
 * @description 从content-disposition中提取文件名
 */
export const extractFileName = (str: string) => {
  if (/filename=([^;\s]*)/gi.test(str)) {
    return decodeURIComponent(RegExp.$1)
  }
  return ''
}

/**
 * @description 文件下载 Blob
 */
export const downloadBlob = (blob: Blob, filename = '') => {
  const a = document.createElement('a')
  a.download = filename
  const blobUrl = URL.createObjectURL(blob)
  a.href = blobUrl
  document.body.appendChild(a)
  a.click()
  a.remove()
  URL.revokeObjectURL(blobUrl)
}

/**
 *
 * @param { String } eleName // elementName
 * @returns { HTMLElement }
 */
export const createFakeDom = <K extends keyof HTMLElementTagNameMap>(eleName: K) => {
  const dom = document.createElement(eleName)
  dom.style.position = 'fixed'
  dom.style.zIndex = '-999999'
  return dom
}

/**
 * @param { Number } number
 * @returns { Number[] } []
 */
export const getNumbers = (n: number, interval: number) => {
  if (!n) {
    return [0]
  }

  if (!interval || n < interval) {
    return [0, n]
  }

  let current = new Big(0)
  const numbers = [0]
  while (current.toNumber() < n) {
    current = current.add(interval)
    const curValue = current.toNumber()
    if (curValue >= n) {
      numbers.push(n)
    } else {
      numbers.push(curValue)
    }
  }
  return numbers
}

/**
 * @return { Number }
 */
export const add = (...args: number[]) => {
  const result = args.reduce((total, n) => {
    return total.add(n)
  }, new Big(0))
  return result.toNumber()
}

/**
 * @return { Number }
 */
export const minus = (num: number, ...args: number[]) => {
  const result = args.reduce((total, n) => {
    return total.minus(n)
  }, new Big(num))
  return result.toNumber()
}

/**
 * @param { any } val
 * @return { Boolean } is HTMLElement
 */

export const isDom = <T extends HTMLElement>(val: any): val is T => {
  return typeof HTMLElement === 'function'
    ? val instanceof HTMLElement
    : val && typeof val === 'object' && val.nodeType === 1 && typeof val.nodeName === 'string'
}

/**
 * @param { Number } time
 * @return { Object }
 */

export const timeFormat = (time: number) => {
  if (!time) {
    return ''
  }
  const DAY = 24 * 60 * 60 * 1000
  const HOUR = 60 * 60 * 1000
  const MINUTE = 60 * 1000
  const SECOND = 1000

  const timeObject: Record<string, number> = {
    d: (time / DAY) | 0,
    h: ((time % DAY) / HOUR) | 0,
    m: ((time % HOUR) / MINUTE) | 0,
    s: ((time % MINUTE) / SECOND) | 0,
  }

  const unitMap: Record<keyof typeof timeObject, string> = {
    d: '天',
    h: '时',
    m: '分',
    s: '秒',
  }

  return Object.entries(unitMap).reduce((format, [key, unit]) => {
    if (timeObject[key] || format) {
      format += `${timeObject[key]} ${unit}`
    }
    return format
  }, '')
}
