type RGBA = number[]

interface TintImageOption {
  imageData: ImageData
  mainColor: RGBA
  distance: number
}

/**
 * @description 白色RGBA
 */
export const WHITE = [255, 255, 255, 255]

/**
 * @description 相似度阀值
 */
export const DISTANCE = 45

const calcPixSim = (rgba: RGBA, base: RGBA = WHITE) => {
  const [r, g, b, a] = rgba
  const [r1, g1, b1, a1] = base
  return Math.sqrt((r - r1) ** 2 + (g - g1) ** 2 + (b - b1) ** 2 + (a - a1) ** 2)
}

const isSimilar = (color1: RGBA, color2: RGBA, distance: number = DISTANCE) => {
  return calcPixSim(color1, color2) <= distance
}

const getColorFromIndex = (index: number, data: Uint8ClampedArray) => {
  return [0, 1, 2, 3].map((_) => {
    return data[index + _]
  })
}

const setColorFromIndex = (index: number, data: Uint8ClampedArray, color: RGBA) => {
  return [0, 1, 2, 3].forEach((_) => {
    data[index + _] = color[_]
  })
}

addEventListener('message', (e) => {
  const imageData = tintImage(e.data)
  postMessage(imageData)
})

const tintImage = ({ mainColor, imageData, distance }: TintImageOption) => {
  const targetColor = [255, 255, 255, 0]
  for (let index = 0; index < imageData.data.length; index++) {
    if (isSimilar(getColorFromIndex(index, imageData.data), mainColor, distance)) {
      setColorFromIndex(index, imageData.data, targetColor)
    }
  }
  return imageData
}
