import type { TixyExpression, TixyRenderOptions, TixyResult } from '../core/types'
import { evaluateTixyExpression } from '../core/evaluator'

export function renderTixyToCanvas(
  expression: TixyExpression,
  options: TixyRenderOptions
): TixyResult {
  const {
    width,
    height,
    time,
    backgroundColor = '#000000',
    foregroundColor = '#ffffff',
    threshold = 0
  } = options

  const canvas = document.createElement('canvas')
  canvas.width = width
  canvas.height = height

  const ctx = canvas.getContext('2d')!
  const imageData = ctx.createImageData(width, height)
  const data = imageData.data

  const bgColor = hexToRgb(backgroundColor)
  const fgColor = hexToRgb(foregroundColor)

  for (let y = 0; y < height; y++) {
    for (let x = 0; x < width; x++) {
      const i = y * width + x
      const value = evaluateTixyExpression(expression, time, i, x, y)

      const intensity = Math.abs(value) > threshold ? Math.min(Math.abs(value), 1) : 0

      const pixelIndex = (y * width + x) * 4

      if (intensity > 0) {
        data[pixelIndex] = Math.round(fgColor.r * intensity + bgColor.r * (1 - intensity))
        data[pixelIndex + 1] = Math.round(fgColor.g * intensity + bgColor.g * (1 - intensity))
        data[pixelIndex + 2] = Math.round(fgColor.b * intensity + bgColor.b * (1 - intensity))
      } else {
        data[pixelIndex] = bgColor.r
        data[pixelIndex + 1] = bgColor.g
        data[pixelIndex + 2] = bgColor.b
      }

      data[pixelIndex + 3] = 255
    }
  }

  ctx.putImageData(imageData, 0, 0)

  return {
    imageData,
    canvas
  }
}

export function renderTixyToImageData(
  expression: TixyExpression,
  options: TixyRenderOptions
): ImageData {
  return renderTixyToCanvas(expression, options).imageData
}

function hexToRgb(hex: string): { r: number; g: number; b: number } {
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
  return result ? {
    r: parseInt(result[1], 16),
    g: parseInt(result[2], 16),
    b: parseInt(result[3], 16)
  } : { r: 0, g: 0, b: 0 }
}