import { ref, onScopeDispose, watch, nextTick, unref, computed, watchEffect } from 'vue'
import type { Ref } from 'vue'
import { isDom } from '@/utils/common'
import TintImageWorker from '@/utils/image.worker?worker'
import useMainStore from '@/store/main'
import { useRoute } from 'vue-router'
import analyze from 'rgbaster'
export type RGBA = number[]

export type Point = [number, number]
export interface SetImgBgOption {
  image?: string | HTMLImageElement | null
  basePoint?: Point[]
  distance?: number
  enableSharpen?: boolean
  rotate?: number
  scale?: number
}

interface InitOption {
  image: string | HTMLImageElement
  frontColor?: Ref<string>
  setFrontColor?: any
}

function getRgba(canvas: any, that: any) {
  const imgWidth = that.width
  const imgHeight = that.height

  canvas.width = imgWidth
  canvas.height = imgHeight

  const context = canvas.getContext('2d')

  context.drawImage(that, 0, 0, imgWidth, imgHeight)
  const imgdatas = context.getImageData(0, 0, imgWidth, imgHeight)
  const imgdata = imgdatas.data
  const newJson: any = {}
  const length = imgdata.length
  console.log('length:' + length)
  for (let i = 0; i < 250; i++) {
    if (i % 4 === 0) {
      const alpha = Math.round((imgdata[i + 3] / 255) * 100) / 100
      const rgba = imgdata[i] + ',' + imgdata[i + 1] + ',' + imgdata[i + 2] + ',' + alpha
      if (!newJson[rgba]) {
        newJson[rgba] = 1
      } else {
        newJson[rgba]++
      }
    }
  }
  let maxNum = 0
  let maxVal = ''
  for (const key in newJson) {
    if (newJson[key] > maxNum) {
      maxNum = newJson[key]
      maxVal = key
    }
  }
  console.log('rgba:', maxVal + ';次数:' + maxNum)
  return maxVal
}
function getHex(...value: any) {
  const r = value[0].toString(16)
  const g = value[1].toString(16)
  const b = value[2].toString(16)
  let hex = r + g + b
  if (r.slice(0, 1) == r.slice(1, 1) && g.slice(0, 1) == g.slice(1, 1) && b.slice(0, 1) == b.slice(1, 1)) {
    hex = r.slice(0, 1) + g.slice(0, 1) + b.slice(0, 1)
  }
  return hex
}

interface MessageData {
  drawing: boolean
  blob?: Blob
}

export const useSetImgBg = (option: Ref<SetImgBgOption>, frontColor?: Ref<string>, setFrontColor?: any) => {
  const { fullPath } = useRoute()
  const mainStore = useMainStore()
  const userSetColor = computed(() => {
    return mainStore.userMarkConfig?.[fullPath]?.frontColor
  })
  watchEffect(() => {
    if (!!userSetColor.value && setFrontColor) {
      setFrontColor(userSetColor.value)
    }
  })
  const initImage = async ({ image, frontColor, setFrontColor }: InitOption) => {
    if (!image) {
      return console.warn(`return for img define ${image}`)
    }

    if (!isDom<HTMLImageElement>(image)) {
      image = await new Promise<HTMLImageElement>((resolve, reject) => {
        const img = new Image()
        img.src = image as string
        img.onload = async () => {
          if (frontColor && setFrontColor) {
            // console.time()
            try {
              const result = await analyze(image, { scale: 0.2 })
              const bgColorRgb = result[0].color
              const bgColorNum = bgColorRgb.split('rgb(')[1].slice(0, -1)
              const splitArr = bgColorNum.split(',')
              const hex = getHex(Number(splitArr[0]), Number(splitArr[1]), Number(splitArr[2]))
              if (!userSetColor?.value) {
                setFrontColor('#' + hex)
              }
            } catch {}
            // console.timeEnd()

            // const canvas = document.createElement('canvas')
            // const maxVal = getRgba(canvas, this)
            // console.log('maxVal:', maxVal)
            // const splitArr = maxVal.split(',')
            // const hex = getHex(Number(splitArr[0]), Number(splitArr[1]), Number(splitArr[2]))
            // if (!userSetColor?.value) {
            //   setFrontColor('#' + hex)
            // }
          }

          resolve(img)
        }
        img.onerror = () => {
          console.log('img error')
          reject()
        }
        img.onabort = () => {
          console.log('img aborted')
          reject()
        }
      })
    }
    return image
  }

  const imageWorker = new TintImageWorker()
  const drawing = ref<boolean>(false)
  const dataUrl = ref('')
  imageWorker.addEventListener('message', (e) => {
    const data = e.data as MessageData
    drawing.value = data.drawing
    dataUrl.value = data.blob ? URL.createObjectURL(data.blob) : ''
  })

  watch(
    [
      () => option.value?.image,
      () => option.value?.distance,
      () => option.value?.basePoint,
      () => option.value?.enableSharpen,
    ],
    () => {
      nextTick(() => {
        const opt = unref(option)
        if (!opt.image) {
          drawing.value = false
          dataUrl.value = ''
          return
        }
        initImage({ image: opt.image, frontColor, setFrontColor })
          .then((image) => {
            if (!image) return
            createImageBitmap(image).then((imageBitMap) => {
              imageWorker.postMessage(
                {
                  type: 'init',
                  imageBitMap,
                  basePoint: opt.basePoint,
                  enableSharpen: opt.enableSharpen,
                  distance: opt.distance,
                  scale: opt.scale,
                  rotate: opt.rotate,
                },
                [imageBitMap]
              )
            })
          })
          .catch((err: any) => {
            drawing.value = false
            dataUrl.value = ''
            console.log('initImage catch err')
          })
      })
    },
    { immediate: true }
  )

  watch(
    () => option.value.scale,
    () => {
      imageWorker.postMessage({ type: 'scale', scale: option.value?.scale })
    }
  )

  watch(
    () => option.value.rotate,
    () => {
      imageWorker.postMessage({ type: 'rotate', rotate: option.value?.rotate })
    }
  )

  watch(dataUrl, (current, prev) => {
    const imgWrapDom = document.querySelector('.img-wrap')
    if (imgWrapDom) {
      setTimeout(() => {
        imgWrapDom.scrollTop = 0
      }, 10)
    }
    if (prev) {
      try {
        URL.revokeObjectURL(prev)
      } catch (error) {}
    }
  })

  onScopeDispose(() => {
    if (dataUrl.value) {
      try {
        URL.revokeObjectURL(dataUrl.value)
      } catch (error) {}
    }
    imageWorker.terminate()
  })

  return {
    drawing,
    dataUrl,
  }
}
