import posterize from "/scratchpad/posterize/posterize.asset.mjs"
import palette from "/scratchpad/_lib/palette.asset.mjs"
import * as random from "/scratchpad/_lib/random.asset.mjs"

const connect = (ctx, points) => {
  points.forEach(([x, y], i) => {
    ctx[i === 0 ? "moveTo" : "lineTo"](x, y)
  })
}

const setup = (canvas) => {
  canvas.width = canvas.height =
    canvas.offsetWidth * window.devicePixelRatio * 0.6
}

const draw = (canvas, isLongPause) => {
  const ctx = canvas.getContext("2d")
  const { width: w, height: h } = canvas

  ctx.clearRect(0, 0, w, h)
  ctx.save()

  const face = [
    // Left cheek
    [random.wobble(w * 0.15, w * 0.10), random.wobble(h * 0.48, h * 0.12)],
    [random.wobble(w * 0.20, w * 0.10), random.wobble(h * 0.25, h * 0.08)],
    [random.wobble(w * 0.30, w * 0.10), random.wobble(h * 0.15, h * 0.08)],
    // Crown
    [random.wobble(w * 0.50, w * 0.10), random.wobble(h * 0.15, h * 0.05)],
    [random.wobble(w * 0.70, w * 0.10), random.wobble(h * 0.15, h * 0.08)],
    [random.wobble(w * 0.80, w * 0.10), random.wobble(h * 0.25, h * 0.08)],
    // Right cheek
    [random.wobble(w * 0.85, w * 0.10), random.wobble(h * 0.48, h * 0.12)],
    [random.wobble(w * 0.80, w * 0.10), random.wobble(h * 0.75, h * 0.15)],
    // Chin
    [random.wobble(w * 0.50, w * 0.10), random.wobble(h * 0.85, h * 0.05)],
    [random.wobble(w * 0.20, w * 0.10), random.wobble(h * 0.75, h * 0.15)],
  ]

  const eye1 = [
    [random.wobble(w * 0.33, w * 0.05), random.wobble(h * 0.38, h * 0.05)],
    [random.wobble(w * 0.33, w * 0.05), random.wobble(h * 0.38, h * 0.05)],
    [random.wobble(w * 0.33, w * 0.05), random.wobble(h * 0.38, h * 0.05)],
    [random.wobble(w * 0.33, w * 0.05), random.wobble(h * 0.38, h * 0.05)],
    [random.wobble(w * 0.33, w * 0.05), random.wobble(h * 0.38, h * 0.05)],
  ]

  const eye2 = [
    [random.wobble(w * 0.67, w * 0.05), random.wobble(h * 0.38, h * 0.05)],
    [random.wobble(w * 0.67, w * 0.05), random.wobble(h * 0.38, h * 0.05)],
    [random.wobble(w * 0.67, w * 0.05), random.wobble(h * 0.38, h * 0.05)],
    [random.wobble(w * 0.67, w * 0.05), random.wobble(h * 0.38, h * 0.05)],
    [random.wobble(w * 0.67, w * 0.05), random.wobble(h * 0.38, h * 0.05)],
  ]

  const mouth = [
    [random.wobble(w * 0.35, w * 0.05), random.wobble(h * 0.60, h * 0.08)],
    [random.wobble(w * 0.45, w * 0.05), random.wobble(h * 0.65, h * 0.04)],
    [random.wobble(w * 0.50, w * 0.05), random.wobble(h * 0.65, h * 0.08)],
    [random.wobble(w * 0.55, w * 0.05), random.wobble(h * 0.65, h * 0.04)],
    [random.wobble(w * 0.65, w * 0.20), random.wobble(h * 0.60, h * 0.08)],
    [random.wobble(w * 0.50, w * 0.05), random.wobble(h * 0.60, h * 0.08)],
    [random.wobble(w * 0.35, w * 0.12), random.wobble(h * 0.60, h * 0.08)],
  ]

  connect(ctx, face)
  ctx.fillStyle = palette.canvas
  ctx.fill()

  posterize({
    ctx,
    radius: w * 0.1,
    ramp: w * 0.1,
    colors: [palette.canvas],
    x: w * 0.1,
    y: h * 0.1,
    width: w * 0.8,
    height: h * 0.8,
  })

  const shift = (arr) => {
    const dx = random.wobble(w * 0.04)
    const dy = random.wobble(w * 0.12)

    arr.forEach((p) => {
      p[0] = p[0] + dx
      p[1] = p[1] + dy
    })
  }

  shift(eye1)
  shift(eye2)

  ctx.beginPath()
  connect(ctx, eye1)
  connect(ctx, eye2)

  ctx.lineJoin = "round"
  ctx.lineCap = "round"
  ctx.strokeStyle = palette.dark
  ctx.lineWidth = random.wobble(w * 0.04, w * 0.02)
  ctx.stroke()

  if (isLongPause) {
    mouth.forEach((p) => {
      p[0] = (p[0] - w / 2) / 2 + w / 2
      p[1] = (p[1] - h / 2) / 2 + h / 2
    })
  }

  ctx.beginPath()
  connect(ctx, mouth)
  ctx.lineWidth = random.wobble(w * 0.06, w * 0.03)
  ctx.stroke()

  // Posterize around each shape
  ;[mouth, eye1, eye2].forEach((shape) => {
    const xs = shape.map((p) => p[0])
    const ys = shape.map((p) => p[1])

    const minX = Math.min(...xs) - w * 0.04
    const maxX = Math.max(...xs) + w * 0.04
    const minY = Math.min(...ys) - w * 0.04
    const maxY = Math.max(...ys) + w * 0.04

    posterize({
      ctx,
      radius: w * 0.03,
      ramp: w * 0.04,
      colors: [palette.canvas],
      x: minX,
      y: minY,
      width: maxX - minX,
      height: maxY - minY,
    })
  })
}

export default async (canvas) => {
  let timeout
  setup(canvas)
  ;(function loop() {
    const isLongPause = random.maybe(0.03)
    draw(canvas, isLongPause)
    timeout = window.setTimeout(loop, isLongPause ? 1000 : 100)
  })()

  return () => window.clearTimeout(timeout)
}