import { Animator, AtlasMeta } from '@/atlas-pack'
import { assertNonNull } from '@/oidlib'
import atlasJSON from './atlas.json' assert { type: 'json' }
import { FilmID } from './film-id.ts'

interface Demo {
  readonly window: Window
  readonly canvas: HTMLCanvasElement
  readonly context: CanvasRenderingContext2D
  readonly animator: Animator
  readonly atlas: HTMLImageElement
  readonly atlasMeta: AtlasMeta<FilmID>
}

async function main(window: Window): Promise<void> {
  console.log(
    `
atlas-pack ┌>°┐
        by │  │idoid
           └──┘
    `.trim(),
  )

  const canvas = window.document.getElementsByTagName('canvas').item(0)
  assertNonNull(canvas, 'Canvas missing.')

  const context = canvas.getContext('2d')
  assertNonNull(context, 'Context missing.')

  // Use nearest neighbor scaling.
  context.imageSmoothingEnabled = false

  const atlas = await loadImage('atlas.png')
  const atlasMeta = atlasJSON as unknown as AtlasMeta<FilmID>
  const film = atlasMeta.filmByID.BackpackerWalkRight
  const demo = {
    window,
    canvas,
    context,
    animator: new Animator(film),
    atlas,
    atlasMeta,
  }
  window.requestAnimationFrame((now) => loop(demo, now, now))
}

function loop(demo: Demo, _then: number, now: number): void {
  demo.context.clearRect(0, 0, demo.canvas.width, demo.canvas.height)

  const scale = 16
  const { bounds } = demo.animator.cel(now)
  const atlasSource = [bounds.x, bounds.y, bounds.w, bounds.h] as const
  const canvasDestination = [0, 0, bounds.w * scale, bounds.h * scale] as const
  demo.context.drawImage(demo.atlas, ...atlasSource, ...canvasDestination)

  demo.window.requestAnimationFrame((then) => loop(demo, now, then))
}

function loadImage(uri: string): Promise<HTMLImageElement> {
  return new Promise((resolve, reject) => {
    const image = new Image()
    image.onload = () => resolve(image)
    image.onerror = () => reject(image)
    image.src = uri
  })
}

await main(window)
