import { expect, test } from "bun:test"
import { RenderProtocol } from "engine/render/RenderProtocol"
import type { RenderInstance } from "engine/render/RenderScene"
import type { Camera } from "engine/scene/Camera"

test("render camera protocol owns its complete shared layout", () => {
  const input: Camera = { position: { x: 1, y: 2, z: 3 }, yaw: 4, pitch: 5, fov: 6 }
  const data = new Float64Array(RenderProtocol.CAMERA_LENGTH)

  RenderProtocol.writeCamera(data, input, 7)
  const output = RenderProtocol.readCamera(data)

  expect(output).toEqual({ camera: input, time: 7 })
  expect(RenderProtocol.VIEW_PROJECTION_LENGTH).toBe(16)
})

test("render instance protocol round-trips scene-local prototype indexes", () => {
  const input: RenderInstance[] = [
    { prototype: 2, x: 1.25, y: -2, z: 3.5, heading: 0.75, scale: 1.5 },
    { prototype: 0, x: -4, y: 5.25, z: 6, heading: -0.5, scale: 0.625 },
  ]
  const ids = new Int32Array(2)
  const transforms = new Float32Array(2 * RenderProtocol.TRANSFORM_FLOATS)
  const output: RenderInstance[] = []

  const count = RenderProtocol.writeInstances(ids, transforms, input)
  RenderProtocol.readInstances(ids, transforms, count, output)

  expect(output).toHaveLength(input.length)
  for (let i = 0; i < input.length; i++) {
    expect(output[i].prototype).toBe(input[i].prototype)
    expect(output[i].x).toBeCloseTo(input[i].x)
    expect(output[i].y).toBeCloseTo(input[i].y)
    expect(output[i].z).toBeCloseTo(input[i].z)
    expect(output[i].heading).toBeCloseTo(input[i].heading)
    expect(output[i].scale).toBeCloseTo(input[i].scale)
  }
})
