import * as CryptoJS from 'crypto-js'

// 表单序列化
export const serialize = (data: Record<string, any>) => {
  const list: string[] = []
  Object.keys(data).forEach((ele) => {
    list.push(`${ele}=${data[ele]}`)
  })
  return list.join('&')
}
export const getObjType = (obj: any) => {
  var toString = Object.prototype.toString
  var map = {
    '[object Boolean]': 'boolean',
    '[object Number]': 'number',
    '[object String]': 'string',
    '[object Function]': 'function',
    '[object Array]': 'array',
    '[object Date]': 'date',
    '[object RegExp]': 'regExp',
    '[object Undefined]': 'undefined',
    '[object Null]': 'null',
    '[object Object]': 'object'
  }
  if (obj instanceof Element) {
    return 'element'
  }
  return map[toString.call(obj) as keyof typeof map]
}
/**
 * 对象深拷贝
 */
export const deepClone = (data: any) => {
  var type = getObjType(data)
  var obj
  if (type === 'array') {
    obj = []
  } else if (type === 'object') {
    obj = {}
  } else {
    // 不再具有下一层次
    return data
  }
  if (type === 'array') {
    for (var i = 0, len = data.length; i < len; i++) {
      ;(obj as any[]).push(deepClone(data[i]))
    }
  } else if (type === 'object') {
    for (var key in data) {
      ;(obj as Record<string, any>)[key] = deepClone(data[key])
    }
  }
  return obj
}
/**
 * 判断路由是否相等
 */
export const diff = (obj1: any, obj2: any): boolean => {
  delete obj1.close
  var o1 = obj1 instanceof Object
  var o2 = obj2 instanceof Object
  if (!o1 || !o2) {
    /*  判断不是对象  */
    return obj1 === obj2
  }

  if (Object.keys(obj1).length !== Object.keys(obj2).length) {
    return false
    // Object.keys() 返回一个由对象的自身可枚举属性(key值)组成的数组,例如：数组返回下表：let arr = ["a", "b", "c"];console.log(Object.keys(arr))->0,1,2;
  }

  for (var attr in obj1) {
    var t1 = obj1[attr] instanceof Object
    var t2 = obj2[attr] instanceof Object
    if (t1 && t2) {
      return diff(obj1[attr], obj2[attr])
    } else if (obj1[attr] !== obj2[attr]) {
      return false
    }
  }
  return true
}

/**
 * diffUrl 判断路由是否相等
 */
export const diffUrl = (route1: any, route2: any) => {
  const value1 = route1.value.split('?')
  const value2 = route2.value.split('?')
  // 同个地址, 不同参数, 替换成新的参数
  if (value1[0] === value2[0]) {
    if (value1[1] === value2[1]) {
      return 1 // 完全相同
    } else {
      return 2 // 参数不同
    }
  } else {
    return 3 // 完全不同
  }
}

/**
 * 设置主题
 */
export const setTheme = (name: string) => {
  document.body.className = name
}

/**
 *加密处理
 */
export const encryption = (params: Record<string, any>) => {
  const { data, type, param } = params
  let { key } = params
  const result = JSON.parse(JSON.stringify(data))
  if (type === 'Base64') {
    param.forEach((ele: string) => {
      result[ele] = btoa(result[ele])
    })
  } else {
    param.forEach((ele: string) => {
      var data = result[ele]
      key = CryptoJS.enc.Latin1.parse(key)
      var iv = key
      // 加密
      var encrypted = CryptoJS.AES.encrypt(data, key, {
        iv: iv,
        mode: CryptoJS.mode.CFB,
        padding: CryptoJS.pad.NoPadding
      })
      result[ele] = encrypted.toString()
    })
  }
  return result
}

/**
 * 动态插入css
 */
export const loadStyle = (url: string) => {
  const link = document.createElement('link')
  link.type = 'text/css'
  link.rel = 'stylesheet'
  link.href = url
  const head = document.getElementsByTagName('head')[0]
  head.appendChild(link)
}

/**
 * @param {Function} func
 * @param {number} wait
 * @param {boolean} immediate
 * @return {*}
 */
export function debounce(func: () => void, wait: number, immediate?: boolean) {
  let timeout: number | null, args: any, context: any, timestamp: number, result: any

  const later = function () {
    // 据上一次触发时间间隔
    const last = +new Date() - timestamp

    // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
    if (last < wait && last > 0) {
      timeout = setTimeout(later, wait - last) as unknown as number
    } else {
      timeout = null
      // 如果设定为immediate===true，因为开始边界已经调用过了此处无需调用
      if (!immediate) {
        result = func.apply(context, args)
        if (!timeout) context = args = null
      }
    }
  }

  return function (this: any, ...args: any) {
    context = this
    timestamp = +new Date()
    const callNow = immediate && !timeout
    // 如果延时不存在，重新设定延时
    if (!timeout) timeout = setTimeout(later, wait) as unknown as number
    if (callNow) {
      result = func.apply(context, args)
      context = args = null
    }

    return result
  }
}

export const getNestedProperty = (obj: Record<string, any>, nestedProperty: string) => {
  const result = nestedProperty.split('.').reduce((pre, cur, index) => {
    if (index === nestedProperty.split('.').length - 1) {
      return pre ? JSON.stringify(pre[cur]) : ''
    } else {
      return pre ? pre[cur] : ''
    }
  }, obj)
  return result as unknown as string
}
