import type { ComputedRef } from 'vue'
import { BLOCK_SIZE, STAGE_WIDTH, STAGE_HEIGHT } from '../level/def'

export default function useLightMap(
  ctx: CanvasRenderingContext2D,
  x: ComputedRef<number>,
  y: ComputedRef<number>,
  tx: ComputedRef<number>,
  ty: ComputedRef<number>,
  time: ComputedRef<number>,
  lightBarrier: ComputedRef<number[]>,
) {
  const W = ((STAGE_WIDTH + 2) * BLOCK_SIZE)
  const H = ((STAGE_HEIGHT + 2) * BLOCK_SIZE)
  const B = BLOCK_SIZE - 4 // no idea why there is a difference, but it is 4px

  const playerX = (W - B) / 2 + B / 4
  const playerY = H / 2 - B / 2
  const playerLightSize = B * 1.8

  function getAmbientLightColor() {
    const t = time.value

    // Night time (pale bluish dark: hslpicker.com/#2b293d )
    if (t > 900 || t < 100) {
      return `hsl(245, 20%, 20%)`
    }
    // Morning hours (gradually more reddish hue)
    if (t < 250) {
      const s = Math.round((t - 100) / 1.5) // 0-100%
      const l = Math.round((t - 100) / 1.875) + 20 // 20-100%
      return `hsl(0, ${s}%, ${l}%)`
    }
    // Evening hours (from neutral white to bluish hue with low saturation)
    if (t > 700) {
      const s = 100 - Math.round((t - 700) / 2.5) // 100-20%
      return `hsl(245, ${s}%, ${s}%)`
    }
    // day (neutral white)
    return `hsl(0, 0%, 100%)`
  }

  function drawPlayerLight(sizeMul:number) {
    const playerLight = ctx.createRadialGradient(
      playerX - tx.value, playerY - ty.value, 0,
      playerX - tx.value, playerY - ty.value, playerLightSize * sizeMul
    )

    // Add color stops: white in the center to transparent white
    playerLight.addColorStop(0.0, "#FFFF");
    playerLight.addColorStop(1, "#FFF0");

    // Set the fill style and draw a rectangle
    ctx.fillStyle = playerLight;
    ctx.fillRect(0, 0, W, H)
  }

  function drawLights() {
    // used for everything above ground
    const ambientLight = getAmbientLightColor()
    const surroundingLight = ambientLight.slice(-2)
    const barrier = lightBarrier.value

    ctx.fillStyle = ambientLight
    for (let col = 0; col < W / B; col++) {
      const level = (barrier[col] - y.value) * B
      const sw = B
      const sh = level
      const sx = col * sw
      const sy = 0

      ctx.fillRect(sx, sy, sw, sh)
    }

    // make light columns wider to illuminate surrounding blocks
    const extra = Math.floor(B / 2)
    const reflectedLight = ambientLight.slice(0, -1) + ', 50%)'
    ctx.fillStyle = reflectedLight
    for (let col = 0; col < W / B; col++) {
      const level = (barrier[col] - y.value) * B
      const sw = B
      const sh = level
      const sx = col * sw
      const sy = 0

      ctx.fillRect(sx - extra, sy - extra, sw + extra * 2, sh + extra * 2)
    }

    // TODO: draw light for candles and torches
  }

  return function update() {
    // first, throw the world in complete darkness
    ctx.fillStyle = '#000'
    ctx.fillRect(0, 0, W, H)

    // second, find and bring light into the world
    drawLights()

    // finally, draw the players light
    // with a size multiplicator which might be later used to
    // simulate greater illumination with candles or torches
    drawPlayerLight(1)
  }
}
