function batchFindObjctValue (obj = {}, keys = []) {
  const values = {}
  for (let i = 0; i < keys.length; i++) {
    const key = keys[i]
    const keyPath = key.split('.')
    let currentKey = keyPath.shift()
    let result = obj
    while (currentKey) {
      if (!result) {
        break
      }
      result = result[currentKey]
      currentKey = keyPath.shift()
    }
    values[key] = result
  }
  return values
}

function getType (val) {
  return Object.prototype.toString.call(val).slice(8, -1).toLowerCase()
}

function hasOwn (obj, key) {
  return Object.prototype.hasOwnProperty.call(obj, key)
}

function isValidString (val) {
  return val && getType(val) === 'string'
}

function isPlainObject (obj) {
  return getType(obj) === 'object'
}

function isFn (fn) {
  // 务必注意AsyncFunction
  return typeof fn === 'function'
}

// 获取文件后缀，只添加几种图片类型供客服消息接口使用
const mime2ext = {
  'image/png': 'png',
  'image/jpeg': 'jpg',
  'image/gif': 'gif',
  'image/svg+xml': 'svg',
  'image/bmp': 'bmp',
  'image/webp': 'webp'
}

function getExtension (contentType) {
  return mime2ext[contentType]
}

const isSnakeCase = /_(\w)/g
const isCamelCase = /[A-Z]/g

function snake2camel (value) {
  return value.replace(isSnakeCase, (_, c) => (c ? c.toUpperCase() : ''))
}

function camel2snake (value) {
  return value.replace(isCamelCase, str => '_' + str.toLowerCase())
}

function parseObjectKeys (obj, type) {
  let parserReg, parser
  switch (type) {
    case 'snake2camel':
      parser = snake2camel
      parserReg = isSnakeCase
      break
    case 'camel2snake':
      parser = camel2snake
      parserReg = isCamelCase
      break
  }
  for (const key in obj) {
    if (hasOwn(obj, key)) {
      if (parserReg.test(key)) {
        const keyCopy = parser(key)
        obj[keyCopy] = obj[key]
        delete obj[key]
        if (isPlainObject(obj[keyCopy])) {
          obj[keyCopy] = parseObjectKeys(obj[keyCopy], type)
        } else if (Array.isArray(obj[keyCopy])) {
          obj[keyCopy] = obj[keyCopy].map((item) => {
            return parseObjectKeys(item, type)
          })
        }
      }
    }
  }
  return obj
}

function snake2camelJson (obj) {
  return parseObjectKeys(obj, 'snake2camel')
}

function camel2snakeJson (obj) {
  return parseObjectKeys(obj, 'camel2snake')
}

function getOffsetDate (offset) {
  return new Date(
    Date.now() + (new Date().getTimezoneOffset() + (offset || 0) * 60) * 60000
  )
}

function getDateStr (date, separator = '-') {
  date = date || new Date()
  const dateArr = []
  dateArr.push(date.getFullYear())
  dateArr.push(('00' + (date.getMonth() + 1)).substr(-2))
  dateArr.push(('00' + date.getDate()).substr(-2))
  return dateArr.join(separator)
}

function getTimeStr (date, separator = ':') {
  date = date || new Date()
  const timeArr = []
  timeArr.push(('00' + date.getHours()).substr(-2))
  timeArr.push(('00' + date.getMinutes()).substr(-2))
  timeArr.push(('00' + date.getSeconds()).substr(-2))
  return timeArr.join(separator)
}

function getFullTimeStr (date) {
  date = date || new Date()
  return getDateStr(date) + ' ' + getTimeStr(date)
}

function getDistinctArray (arr) {
  return Array.from(new Set(arr))
}

/**
 * 拼接url
 * @param {string} base 基础路径
 * @param {string} path 在基础路径上拼接的路径
 * @returns
 */
function resolveUrl (base, path) {
  if (/^https?:/.test(path)) {
    return path
  }
  return base + path
}

function getVerifyCode (len = 6) {
  let code = ''
  for (let i = 0; i < len; i++) {
    code += Math.floor(Math.random() * 10)
  }
  return code
}

function coverMobile (mobile) {
  if (typeof mobile !== 'string') {
    return mobile
  }
  return mobile.slice(0, 3) + '****' + mobile.slice(7)
}

function getNonceStr (length = 16) {
  let str = ''
  while (str.length < length) {
    str += Math.random().toString(32).substring(2)
  }
  return str.substring(0, length)
}

try {
  require('lodash.merge')
} catch (error) {
  console.error('uni-id-co缺少依赖，请在uniCloud/cloudfunctions/uni-id-co目录执行 npm install 安装依赖')
  throw error
}

function isMatchUserApp (userAppList, matchAppList) {
  if (userAppList === undefined || userAppList === null) {
    return true
  }
  if (getType(userAppList) !== 'array') {
    return false    
  }
  if (userAppList.includes('*')) {
    return true
  }
  if (getType(matchAppList) === 'string') {
    matchAppList = [matchAppList]
  }
  return userAppList.some(item => matchAppList.includes(item))
}

module.exports = {
  getType,
  isValidString,
  batchFindObjctValue,
  isPlainObject,
  isFn,
  getDistinctArray,
  getFullTimeStr,
  resolveUrl,
  getOffsetDate,
  camel2snakeJson,
  snake2camelJson,
  getExtension,
  getVerifyCode,
  coverMobile,
  getNonceStr,
  isMatchUserApp
}
