///|
/// Frame profiler data. Collect timing in update/draw and pass to `build_profiler_hud`.
pub(all) struct FrameProfile {
  fps : Double
  frame_time_ms : Double
  update_ms : Double
  draw_ms : Double
  gpu_frame_ms : Double
  draw_calls : Int
  vertex_count : Int
  asset_inflight : Int
} derive(Debug)

///|
pub impl Show for FrameProfile with output(self, logger) {
  logger.write_object(to_repr(self))
}

///|
pub fn default_frame_profile() -> FrameProfile {
  {
    fps: 0.0,
    frame_time_ms: 0.0,
    update_ms: 0.0,
    draw_ms: 0.0,
    gpu_frame_ms: 0.0,
    draw_calls: 0,
    vertex_count: 0,
    asset_inflight: 0,
  }
}

///|
/// Build a profiler HUD overlay in the top-right corner.
/// Uses dot-matrix glyphs — no font dependency.
pub fn build_profiler_hud(
  cmds : Array[@gfx.DrawTrianglesCommand],
  dst : @gfx.ImageHandle,
  shader : @gfx.ShaderHandle,
  profile : FrameProfile,
  screen_w : Double,
  screen_h : Double,
) -> Unit {
  let scale = 1.0
  let line_h = 20.0
  let margin = 8.0
  let x = screen_w - 80.0
  let mut y = margin + 10.0
  let bg_color = color_from_hex_alpha(0x000000, 0.5)
  let text_color = color_from_hex_alpha(0x00FF00, 0.9)
  let warn_color = color_from_hex_alpha(0xFFFF00, 0.9)
  // Background
  cmds.push(
    new_ndc_rect_fill_command(
      dst,
      shader,
      screen_w - 160.0,
      0.0,
      160.0,
      margin + line_h * 8.0 + margin,
      screen_w,
      screen_h,
      bg_color,
      0,
    ),
  )
  // FPS (yellow if < 30)
  let fps_int = profile.fps.to_int()
  let fps_color = if fps_int < 30 { warn_color } else { text_color }
  // "FPS" label + number
  draw_dot_text(
    cmds,
    dst,
    shader,
    [70, 80, 83],
    x - 30.0,
    y,
    screen_w,
    screen_h,
    text_color,
    scale,
  )
  draw_number(
    cmds,
    dst,
    shader,
    fps_int,
    x + 20.0,
    y,
    screen_w,
    screen_h,
    fps_color,
    scale,
  )
  y = y + line_h
  // Frame time
  draw_dot_text(
    cmds,
    dst,
    shader,
    [70, 84],
    x - 30.0,
    y,
    screen_w,
    screen_h,
    text_color,
    scale,
  )
  draw_number(
    cmds,
    dst,
    shader,
    profile.frame_time_ms.to_int(),
    x + 20.0,
    y,
    screen_w,
    screen_h,
    text_color,
    scale,
  )
  y = y + line_h
  // Update ms
  draw_dot_text(
    cmds,
    dst,
    shader,
    [85, 80],
    x - 30.0,
    y,
    screen_w,
    screen_h,
    text_color,
    scale,
  )
  draw_number(
    cmds,
    dst,
    shader,
    profile.update_ms.to_int(),
    x + 20.0,
    y,
    screen_w,
    screen_h,
    text_color,
    scale,
  )
  y = y + line_h
  // Draw ms
  draw_dot_text(
    cmds,
    dst,
    shader,
    [68, 82],
    x - 30.0,
    y,
    screen_w,
    screen_h,
    text_color,
    scale,
  )
  draw_number(
    cmds,
    dst,
    shader,
    profile.draw_ms.to_int(),
    x + 20.0,
    y,
    screen_w,
    screen_h,
    text_color,
    scale,
  )
  y = y + line_h
  // GPU frame ms
  draw_dot_text(
    cmds,
    dst,
    shader,
    [71, 80],
    x - 30.0,
    y,
    screen_w,
    screen_h,
    text_color,
    scale,
  )
  draw_number(
    cmds,
    dst,
    shader,
    profile.gpu_frame_ms.to_int(),
    x + 20.0,
    y,
    screen_w,
    screen_h,
    text_color,
    scale,
  )
  y = y + line_h
  // Draw calls
  draw_dot_text(
    cmds,
    dst,
    shader,
    [68, 67],
    x - 30.0,
    y,
    screen_w,
    screen_h,
    text_color,
    scale,
  )
  draw_number(
    cmds,
    dst,
    shader,
    profile.draw_calls,
    x + 20.0,
    y,
    screen_w,
    screen_h,
    text_color,
    scale,
  )
  y = y + line_h
  // Vertices
  draw_dot_text(
    cmds,
    dst,
    shader,
    [86, 84],
    x - 30.0,
    y,
    screen_w,
    screen_h,
    text_color,
    scale,
  )
  draw_number(
    cmds,
    dst,
    shader,
    profile.vertex_count,
    x + 20.0,
    y,
    screen_w,
    screen_h,
    text_color,
    scale,
  )
  y = y + line_h
  // Asset inflight
  draw_dot_text(
    cmds,
    dst,
    shader,
    [65, 83],
    x - 30.0,
    y,
    screen_w,
    screen_h,
    text_color,
    scale,
  )
  draw_number(
    cmds,
    dst,
    shader,
    profile.asset_inflight,
    x + 20.0,
    y,
    screen_w,
    screen_h,
    text_color,
    scale,
  )
}