import { createApp } from 'vue'

/**
 * 防抖函数
 *
 * @param {*} fn 回调方法
 * @param {*} delay 延迟时间
 * @returns
 */
export function debounce(fn, delay) {
  let timer = null

  return function () {
    timer && clearTimeout(timer)

    let content = this
    let args = arguments
    timer = setTimeout(() => {
      fn.apply(content, args)
    }, delay)
  }
}

/**
 * 节流函数
 *
 * @param {*} fn 回调方法
 * @param {*} delay 延迟时间
 * @returns
 */
export function throttle(fn, delay, call = function () {}) {
  let lastTime = 0

  return function () {
    // 获取当前时间戳
    let now = new Date().getTime()

    // 如果当前时间减去上次时间大于限制时间时才执行
    if (now - lastTime > delay) {
      lastTime = now
      fn.apply(this, arguments)
    } else {
      call()
    }
  }
}

/**
 * 剪贴板复制功能
 *
 * @param {String} text 复制内容
 * @param {Function} callback 复制成功回调方法
 */
export function clipboard(text, callback) {
  navigator.clipboard
    .writeText(text)
    .then(() => {
      callback && callback()
    })
    .catch(() => {
      alert('Oops, unable to copy')
    })
}

export async function clipboardImage(src, callback) {
  const { state } = await navigator.permissions.query({
    name: 'clipboard-write',
  })

  if (state != 'granted') return

  try {
    const data = await fetch(src)
    const blob = await data.blob()

    // navigator.clipboard.write 仅支持 png 图片
    if (blob.type == 'image/png') {
      await navigator.clipboard.write([
        new ClipboardItem({
          [blob.type]: blob,
        }),
      ])

      return callback()
    }

    const objectURL = URL.createObjectURL(blob)

    const img = new Image()
    img.src = URL.createObjectURL(blob)
    img.onload = () => {
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')

      canvas.width = img.width
      canvas.height = img.height
      ctx.drawImage(img, 0, 0)

      canvas.toBlob(
        (blob) => {
          const data = [new ClipboardItem({ [blob.type]: blob })]

          navigator.clipboard
            .write(data)
            .then(() => {
              callback()
            })
            .catch((err) => {
              console.error(err)
            })

          URL.revokeObjectURL(objectURL)
        },
        'image/png',
        1,
      )
    }
  } catch (err) {
    console.error(err.name, err.message)
  }
}

export function hashStrToHexColor(str) {
  let hash = 0
  for (let i = 0; i < str.length; i++) {
    hash = str.charCodeAt(i) + ((hash << 5) - hash)
  }
  let color = '#'
  for (let i = 0; i < 3; i++) {
    const value = (hash >> (i * 8)) & 0xff
    color += value.toString(16).padStart(2, '0')
  }
  return color
}

export function emitCall(event, data, fn) {
  return { event: event, data: data, callBack: fn || function () {} }
}

// 判断是否是客户端模式
export function isElectronMode() {
  return electron() != undefined
}

export function electron() {
  return window.electron
}

export function htmlDecode(input) {
  return input
    .replace(/&amp;/g, '&')
    .replace(/&#39;/g, "'")
    .replace(/&lt;/g, '<')
    .replace(/&gt;/g, '>')
    .replace(/&#34;/g, '"')
}

// 文件转 图片 关键函数  异步
export function getVideoImage(file, time = 1) {
  return new Promise((resolve) => {
    let video = document.createElement('video')

    const objectURL = URL.createObjectURL(file)

    video.src = objectURL
    video.currentTime = time
    video.autoplay = true
    video.muted = true

    video.onloadeddata = () => {
      let canvas = document.createElement('canvas')
      canvas.width = video.videoWidth
      canvas.height = video.videoHeight

      let ctx = canvas.getContext('2d')
      ctx?.drawImage(video, 0, 0, canvas.width, canvas.height)

      let data = {
        url: canvas.toDataURL('image/jpeg', 1),
        width: video.videoWidth,
        height: video.videoHeight,
        duration: video.duration,
        file: null,
      }

      canvas.toBlob((blob) => {
        data.file = new File([blob], 'image.jpeg', {
          type: blob.type,
          lastModified: Date.now(),
        })

        URL.revokeObjectURL(objectURL)

        resolve(data)
      }, 'image/jpeg')
    }
  })
}

//处理webview样式
export function handleSetWebviewStyle(hasTabBar) {
  const setWebviewStyle = () => {
    const webview = plus.webview.currentWebview()
    webview.setStyle({
      bottom: hasTabBar ? webview.tabBarHeight : 0,
    })
  }
  if (typeof plus !== 'undefined') {
    setWebviewStyle()
  } else {
    document.addEventListener('plusready', () => {
      setWebviewStyle()
    })
  }
}

//遍历所有的webview并通信
export function handleFindWebview(evalJS_) {
  const findWebview = () => {
    let allWebView = plus.webview.all()
    allWebView.forEach((webview) => {
      //由于webviewId后面的数字是动态分配的，在很小情况下OAWebview的Id并不是webviewId1
      //因此不做限制，全局广播，由接收页面自行接收处理
      // if (webview.id === 'webviewId1') {//找到OAWebview
      webview.evalJS(evalJS_)
      // }
    })
  }
  if (typeof plus !== 'undefined') {
    findWebview()
  } else {
    document.addEventListener('plusready', () => {
      findWebview()
    })
  }
}

// 通用运算函数
/*
    函数，加法函数，用来得到精确的加法结果
    说明：javascript的加法结果会有误差，在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
    参数：arg1：第一个加数；arg2第二个加数；d要保留的小数位数（可以不传此参数，如果不传则不处理小数位数）
    调用：Calc.Add(arg1,arg2,d)
    返回值：两数相加的结果
*/
export function addition(arg1, arg2) {
  ;(arg1 = arg1.toString()), (arg2 = arg2.toString())
  var arg1Arr = arg1.split('.'),
    arg2Arr = arg2.split('.'),
    d1 = arg1Arr.length == 2 ? arg1Arr[1] : '',
    d2 = arg2Arr.length == 2 ? arg2Arr[1] : ''
  var maxLen = Math.max(d1.length, d2.length)
  var m = Math.pow(10, maxLen)
  var result = Number(((arg1 * m + arg2 * m) / m).toFixed(maxLen))
  var d = arguments[2]
  return typeof d === 'number' ? Number(result.toFixed(d)) : result
}

/*
    函数：减法函数，用来得到精确的减法结果
    说明：函数返回较为精确的减法结果。
    参数：arg1：第一个加数；arg2第二个加数；d要保留的小数位数（可以不传此参数，如果不传则不处理小数位数)
    调用：Calc.Sub(arg1,arg2)
    返回值：两数相减的结果
*/

/*
    函数：乘法函数，用来得到精确的乘法结果
    说明：函数返回较为精确的乘法结果。
    参数：arg1：第一个乘数；arg2第二个乘数；d要保留的小数位数（可以不传此参数，如果不传则不处理小数位数)
    调用：Calc.Mul(arg1,arg2)
    返回值：两数相乘的结果
*/
export function multiplication(arg1, arg2) {
  var r1 = arg1.toString(),
    r2 = arg2.toString(),
    m,
    resultVal,
    d = arguments[2]
  m =
    (r1.split('.')[1] ? r1.split('.')[1].length : 0) +
    (r2.split('.')[1] ? r2.split('.')[1].length : 0)
  resultVal =
    (Number(r1.replace('.', '')) * Number(r2.replace('.', ''))) /
    Math.pow(10, m)
  return typeof d !== 'number'
    ? Number(resultVal)
    : Number(resultVal.toFixed(parseInt(d)))
}

/*
    函数：除法函数，用来得到精确的除法结果
    说明：函数返回较为精确的除法结果。
    参数：arg1：除数；arg2被除数；d要保留的小数位数（可以不传此参数，如果不传则不处理小数位数)
    调用：Calc.Div(arg1,arg2)
    返回值：arg1除于arg2的结果
*/
export function division(arg1, arg2) {
  var r1 = arg1.toString(),
    r2 = arg2.toString(),
    m,
    resultVal,
    d = arguments[2]
  m =
    (r2.split('.')[1] ? r2.split('.')[1].length : 0) -
    (r1.split('.')[1] ? r1.split('.')[1].length : 0)
  resultVal =
    (Number(r1.replace('.', '')) / Number(r2.replace('.', ''))) *
    Math.pow(10, m)
  return typeof d !== 'number'
    ? Number(resultVal)
    : Number(resultVal.toFixed(parseInt(d)))
}
