/**
 *
 * @param component 需要注册的组件
 * @param alias 组件别名
 * @returns any
 */
export const withInstall = <T>(component: T, alias?: string) => {
  const comp = component as any
  comp.install = (app: any) => {
    app.component(comp.name || comp.displayName, component)
    if (alias) {
      app.config.globalProperties[alias] = component
    }
  }
  return component as T & Plugin
}

/**
 * @param str 需要转下划线的驼峰字符串
 * @returns 字符串下划线
 */
export const humpToUnderline = (str: string): string => {
  return str.replace(/([A-Z])/g, '-$1').toLowerCase()
}

/**
 * @param str 需要转驼峰的下划线字符串
 * @returns 字符串驼峰
 */
export const underlineToHump = (str: string): string => {
  if (!str) return ''
  return str.replace(/\-(\w)/g, (_, letter: string) => {
    return letter.toUpperCase()
  })
}

/**
 * 驼峰转横杠
 */
export const humpToDash = (str: string): string => {
  return str.replace(/([A-Z])/g, '-$1').toLowerCase()
}

export const setCssVar = (prop: string, val: any, dom = document.documentElement) => {
  dom.style.setProperty(prop, val)
}

export const getCssVar = (prop: string, dom = document.documentElement) => {
  return getComputedStyle(dom).getPropertyValue(prop)
}

/**
 * 查找数组对象的某个下标
 * @param {Array} ary 查找的数组
 * @param {Functon} fn 判断的方法
 */
export const findIndex = <T = Recordable>(ary: Array<T>, fn: Fn): number => {
  if (ary.findIndex) {
    return ary.findIndex(fn)
  }
  let index = -1
  ary.some((item: T, i: number, ary: Array<T>) => {
    const ret: T = fn(item, i, ary)
    if (ret) {
      index = i
      return ret
    }
  })
  return index
}

export const trim = (str: string) => {
  return str.replace(/(^\s*)|(\s*$)/g, '')
}

/**
 * @param {Date | number | string} time 需要转换的时间
 * @param {String} fmt 需要转换的格式 如 yyyy-MM-dd、yyyy-MM-dd HH:mm:ss
 */
export function formatTime(time: Date | number | string, fmt: string) {
  if (!time) return ''
  else {
    const date = new Date(time)
    const o = {
      'M+': date.getMonth() + 1,
      'd+': date.getDate(),
      'H+': date.getHours(),
      'm+': date.getMinutes(),
      's+': date.getSeconds(),
      'q+': Math.floor((date.getMonth() + 3) / 3),
      S: date.getMilliseconds()
    }
    if (/(y+)/.test(fmt)) {
      fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
    }
    for (const k in o) {
      if (new RegExp('(' + k + ')').test(fmt)) {
        fmt = fmt.replace(
          RegExp.$1,
          RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
        )
      }
    }
    return fmt
  }
}

/**
 * 生成随机字符串
 */
export function toAnyString() {
  const str: string = 'xxxxx-xxxxx-4xxxx-yxxxx-xxxxx'.replace(/[xy]/g, (c: string) => {
    const r: number = (Math.random() * 16) | 0
    const v: number = c === 'x' ? r : (r & 0x3) | 0x8
    return v.toString()
  })
  return str
}

/**
 * 首字母大写
 */
export function firstUpperCase(str: string) {
  return str.toLowerCase().replace(/( |^)[a-z]/g, (L) => L.toUpperCase())
}

/**
 * 把对象转为formData
 */
export function objToFormData(obj: Recordable) {
  const formData = new FormData()
  Object.keys(obj).forEach((key) => {
    formData.append(key, obj[key])
  })
  return formData
}

/**
 * 查询字典表数据
 * 传递value 表示要去到value===codeValue对应的codeName
 * @params1 第一个参数 type 字典类型
 * @params2 第二个参数 codeValue 传递value
 * @params3 第三个参数 boolean 是否使用number类型的值作为value字段
 */
export function getCodeByType(type: string, ...args: any[]) {
  const sessionCodeList = sessionStorage.getItem('CODE_ENUM')
  if (sessionCodeList) {
    const list = JSON.parse(sessionCodeList)
      .filter((i) => i.codeType === type)
      .map((j) => {
        return {
          value: args[1] === true ? Number(j.codeValue) : j.codeValue,
          label: j.codeName
        }
      })
    // 传了第二个参数  表示要获取对应字段名称 没传则代表获取的是字典数组数据
    return args.length > 0
      ? args[0] === undefined
        ? ''
        : list.find((i) => i.value == args[0])?.label
      : list
  }
  return args.length > 0 ? '' : []
}

/**
 * 获取全局部门树结构
 *
 * 该函数从sessionStorage中获取名为'DEPT_TREE'的项，将其解析为JSON对象并返回
 * 如果项不存在或解析失败，则返回一个空数组
 *
 * @returns {Array} 部门树结构数组，如果不存在则返回空数组
 */
export const globalDeptTree = () => {
  // 从sessionStorage获取部门树结构字符串
  const tree = sessionStorage.getItem('DEPT_TREE')
  // 如果获取到字符串，则解析为JSON对象；否则返回空数组
  return tree ? JSON.parse(tree) : []
}

/**
 * 获取全局的区域树数据
 *
 * 该函数从sessionStorage中获取名为'DISTRICT_TREE'的项，并将其解析为JSON对象
 * 如果该项不存在，则返回一个空数组
 *
 * @returns {Array} 解析后的区域树数据数组，如果sessionStorage中没有相关数据，则返回空数组
 */
export const globalDistrictTree = () => {
  const tree = sessionStorage.getItem('DISTRICT_TREE')
  return tree ? JSON.parse(tree) : []
}

//获取路径上的参数
export const getQueryString = (name) => {
  const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`)
  const r = window.location.search.substr(1).match(reg)
  if (r != null) {
    return unescape(r[2])
  }
  return null
}

interface IPathParam {
  paramName: string
  paramValue: string
}
export const setPathParam = (params: IPathParam[]) => {
  // 获取当前 URL 的参数
  const searchParams = new URLSearchParams(window.location.search)
  // 修改参数值
  for (const i of params) {
    searchParams.set(i.paramName, i.paramValue)
  }
  // searchParams.set('currentPage', currentPage.value.toString())
  // 创建一个新的 URL，但不替换当前的 URL，也不刷新页面
  const newUrl = `${window.location.origin}${window.location.hash.split('?')[0]}?${searchParams.toString()}`
  // 使用 pushState 替换当前的 URL，但不刷新页面
  window.history.pushState({}, '', newUrl)
}
