# Phase 27 Part 2: The CRT Scanline Renderer
import term_font
import ion_client

const TERM_COLS* = 100
const TERM_ROWS* = 37

# Sovereign Palette (Phased Aesthetics)
const
  COLOR_SOVEREIGN_BLUE = 0xFF401010'u32
  COLOR_PHOSPHOR_AMBER = 0xFF00B0FF'u32
  COLOR_SCANLINE_DIM = 0xFF300808'u32

var grid: array[TERM_ROWS, array[TERM_COLS, char]]
var cursor_x, cursor_y: int
var color_fg: uint32 = COLOR_PHOSPHOR_AMBER
var color_bg: uint32 = COLOR_SOVEREIGN_BLUE
var fb_ptr: ptr UncheckedArray[uint32]
var fb_w, fb_h, fb_stride: int
var ansi_state: int = 0

proc term_init*() =
  let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
  fb_ptr = cast[ptr UncheckedArray[uint32]](sys.fb_addr)
  fb_w = int(sys.fb_width)
  fb_h = int(sys.fb_height)
  fb_stride = int(sys.fb_stride)
  cursor_x = 0
  cursor_y = 0
  ansi_state = 0

  # Initialize Grid
  for row in 0..<TERM_ROWS:
    for col in 0..<TERM_COLS:
      grid[row][col] = ' '

  # Force initial color compliance
  color_fg = COLOR_PHOSPHOR_AMBER
  color_bg = COLOR_SOVEREIGN_BLUE

proc term_clear*() =
  for row in 0..<TERM_ROWS:
    for col in 0..<TERM_COLS:
      grid[row][col] = ' '
  cursor_x = 0
  cursor_y = 0
  ansi_state = 0

proc term_scroll() =
  for row in 0..<(TERM_ROWS-1):
    grid[row] = grid[row + 1]
  for col in 0..<TERM_COLS:
    grid[TERM_ROWS-1][col] = ' '

proc term_putc*(ch: char) =
  # ANSI Stripper
  if ansi_state == 1:
    if ch == '[': ansi_state = 2
    else: ansi_state = 0
    return
  if ansi_state == 2:
    if ch >= '@' and ch <= '~': ansi_state = 0
    return
  if ch == '\x1b':
    ansi_state = 1
    return

  if ch == '\n':
    cursor_x = 0
    cursor_y += 1
  elif ch == '\r':
    cursor_x = 0
  elif ch >= ' ':
    if cursor_x >= TERM_COLS:
      cursor_x = 0
      cursor_y += 1
    if cursor_y >= TERM_ROWS:
      term_scroll()
      cursor_y = TERM_ROWS - 1
    grid[cursor_y][cursor_x] = ch
    cursor_x += 1

# --- THE GHOST RENDERER ---
proc draw_char(cx, cy: int, c: char, fg: uint32, bg: uint32) =
  if fb_ptr == nil: return

  # Safe Font Mapping
  var glyph_idx = int(c) - 32
  if glyph_idx < 0 or glyph_idx >= 96: glyph_idx = 0 # Space default

  let px_start = cx * 8
  let py_start = cy * 16

  for y in 0..15:
    # Scanline Logic: Every 4th line
    let is_scanline = (y mod 4) == 3

    let row_bits = FONT_BITMAP[glyph_idx][y]
    let screen_y = py_start + y
    if screen_y >= fb_h: break

    # Optimize inner loop knowing stride is in bytes but using uint32 accessor
    # fb_ptr index is per uint32.
    let row_offset = screen_y * (fb_stride div 4)

    for x in 0..7:
      let screen_x = px_start + x
      if screen_x >= fb_w: break

      let pixel_idx = row_offset + screen_x

      # Bit Check: MSB first (0x80 >> x)
      let is_pixel = ((int(row_bits) shr (7 - x)) and 1) != 0

      if is_pixel:
        if is_scanline:
          fb_ptr[pixel_idx] = fg and 0xFFE0E0E0'u32
        else:
          fb_ptr[pixel_idx] = fg
      else:
        if is_scanline:
          fb_ptr[pixel_idx] = COLOR_SCANLINE_DIM
        else:
          fb_ptr[pixel_idx] = bg

proc term_render*() =
  if fb_ptr == nil: return
  for row in 0..<TERM_ROWS:
    for col in 0..<TERM_COLS:
      draw_char(col, row, grid[row][col], color_fg, color_bg)
