// src/wasm_bindings.mbt
// WASM exports and rendering layer using Canvas FFI

let global_game : Ref[Option[Game]] = { val: None }

pub fn wasm_new_game() -> Unit {
  global_game.val = Some(Game::new())
}

pub fn wasm_tick() -> Unit {
  match global_game.val {
    Some(g) => g.tick()
    None => ()
  }
}

pub fn wasm_move_left() -> Unit {
  match global_game.val {
    Some(g) => { let _ = g.move_left(); }
    None => ()
  }
}

pub fn wasm_move_right() -> Unit {
  match global_game.val {
    Some(g) => { let _ = g.move_right(); }
    None => ()
  }
}

pub fn wasm_rotate() -> Unit {
  match global_game.val {
    Some(g) => { let _ = g.rotate(); }
    None => ()
  }
}

pub fn wasm_soft_drop() -> Unit {
  match global_game.val {
    Some(g) => { let _ = g.soft_drop(); }
    None => ()
  }
}

pub fn wasm_hard_drop() -> Unit {
  match global_game.val {
    Some(g) => g.hard_drop()
    None => ()
  }
}

pub fn wasm_hold() -> Unit {
  match global_game.val {
    Some(g) => g.hold()
    None => ()
  }
}

pub fn wasm_is_game_over() -> Bool {
  match global_game.val {
    Some(g) => g.game_over
    None => true
  }
}

pub fn wasm_get_score() -> Int {
  match global_game.val {
    Some(g) => g.score
    None => 0
  }
}

pub fn wasm_get_lines() -> Int {
  match global_game.val {
    Some(g) => g.lines
    None => 0
  }
}

pub fn wasm_get_level() -> Int {
  match global_game.val {
    Some(g) => g.level
    None => 1
  }
}

fn draw_block(x : Double, y : Double, kind : Int, is_ghost : Bool) -> Unit {
  let size = 28.0
  let (r, g, b) = match kind {
    1 => (0, 243, 255)  // Cyber Cyan
    2 => (255, 235, 59)  // Neon Yellow
    3 => (188, 79, 255)  // Cyber Purple
    4 => (0, 230, 118)  // Neon Green
    5 => (255, 23, 68)   // Neon Red
    6 => (41, 121, 255)  // Neon Blue
    7 => (255, 145, 0)   // Neon Orange
    _ => (20, 20, 25)
  }
  
  if kind > 0 {
    if is_ghost {
      set_stroke_color(r, g, b)
      set_line_width(1.5)
      stroke_rect(x + 2.0, y + 2.0, size - 4.0, size - 4.0)
    } else {
      set_fill_color(r, g, b)
      fill_rect(x + 1.0, y + 1.0, size - 2.0, size - 2.0)
      set_fill_color(255, 255, 255)
      fill_rect(x + 2.0, y + 2.0, size - 4.0, 3.0)
      fill_rect(x + 2.0, y + 2.0, 3.0, size - 4.0)
    }
  } else {
    set_fill_color(24, 24, 30)
    fill_rect(x, y, size, size)
    set_stroke_color(36, 36, 45)
    set_line_width(0.5)
    stroke_rect(x, y, size, size)
  }
}

fn draw_small_piece(center_x : Double, center_y : Double, kind : Int) -> Unit {
  if kind == 0 { return }
  let n = if kind == 1 { 4 } else if kind == 2 { 2 } else { 3 }
  let block_size = 18.0
  let offset_x = center_x - (n.to_double() * block_size) / 2.0
  let offset_y = center_y - (n.to_double() * block_size) / 2.0
  
  let (r, g, b) = match kind {
    1 => (0, 243, 255)
    2 => (255, 235, 59)
    3 => (188, 79, 255)
    4 => (0, 230, 118)
    5 => (255, 23, 68)
    6 => (41, 121, 255)
    7 => (255, 145, 0)
    _ => (0, 0, 0)
  }
  
  set_fill_color(r, g, b)
  for row = 0; row < n; row = row + 1 {
    for col = 0; col < n; col = col + 1 {
      if get_block(kind, 0, row, col) {
        let x = offset_x + col.to_double() * block_size
        let y = offset_y + row.to_double() * block_size
        fill_rect(x + 1.0, y + 1.0, block_size - 2.0, block_size - 2.0)
      }
    }
  }
}

pub fn wasm_render() -> Unit {
  match global_game.val {
    Some(g) => {
      clear_rect(0.0, 0.0, 600.0, 600.0)
      
      set_fill_color(30, 30, 40)
      fill_rect(20.0, 20.0, 110.0, 110.0)
      set_stroke_color(70, 70, 90)
      set_line_width(2.0)
      stroke_rect(20.0, 20.0, 110.0, 110.0)
      
      set_fill_color(180, 180, 200)
      set_font("bold 14px Outfit")
      fill_text("HOLD", 55.0, 42.0)
      
      set_fill_color(30, 30, 40)
      fill_rect(470.0, 20.0, 110.0, 110.0)
      set_stroke_color(70, 70, 90)
      stroke_rect(470.0, 20.0, 110.0, 110.0)
      
      set_fill_color(180, 180, 200)
      fill_text("NEXT", 505.0, 42.0)
      
      draw_small_piece(75.0, 85.0, g.hold_kind)
      draw_small_piece(525.0, 85.0, g.next_kind)
      
      set_fill_color(30, 30, 40)
      fill_rect(470.0, 150.0, 110.0, 150.0)
      stroke_rect(470.0, 150.0, 110.0, 150.0)
      
      set_fill_color(140, 140, 160)
      set_font("12px Outfit")
      fill_text("SCORE", 480.0, 180.0)
      set_fill_color(255, 255, 255)
      set_font("bold 18px JetBrains Mono")
      fill_text(g.score.to_string(), 480.0, 202.0)
      
      set_fill_color(140, 140, 160)
      set_font("12px Outfit")
      fill_text("LEVEL", 480.0, 230.0)
      set_fill_color(0, 243, 255)
      set_font("bold 18px JetBrains Mono")
      fill_text(g.level.to_string(), 480.0, 252.0)
      
      set_fill_color(140, 140, 160)
      set_font("12px Outfit")
      fill_text("LINES", 480.0, 280.0)
      set_fill_color(255, 255, 255)
      set_font("bold 18px JetBrains Mono")
      fill_text(g.lines.to_string(), 480.0, 302.0)
      
      let board_x = 160.0
      let board_y = 20.0
      set_stroke_color(100, 100, 130)
      stroke_rect(board_x - 2.0, board_y - 2.0, 284.0, 564.0)
      
      for row = 0; row < 20; row = row + 1 {
        for col = 0; col < 10; col = col + 1 {
          let x = board_x + col.to_double() * 28.0
          let y = board_y + row.to_double() * 28.0
          draw_block(x, y, g.board[row][col], false)
        }
      }
      
      if !g.game_over {
        let mut ghost_y = g.current_y
        while !g.check_collision(g.current_x, ghost_y + 1, g.current_rotation) {
          ghost_y = ghost_y + 1
        }
        
        let n = if g.current_kind == 1 { 4 } else if g.current_kind == 2 { 2 } else { 3 }
        for row = 0; row < n; row = row + 1 {
          for col = 0; col < n; col = col + 1 {
            if get_block(g.current_kind, g.current_rotation, row, col) {
              let by = ghost_y + row
              if by >= 0 {
                let bx = g.current_x + col
                let x = board_x + bx.to_double() * 28.0
                let y = board_y + by.to_double() * 28.0
                draw_block(x, y, g.current_kind, true)
              }
            }
          }
        }
      }
      
      if !g.game_over {
        let n = if g.current_kind == 1 { 4 } else if g.current_kind == 2 { 2 } else { 3 }
        for row = 0; row < n; row = row + 1 {
          for col = 0; col < n; col = col + 1 {
            if get_block(g.current_kind, g.current_rotation, row, col) {
              let by = g.current_y + row
              if by >= 0 {
                let bx = g.current_x + col
                let x = board_x + bx.to_double() * 28.0
                let y = board_y + by.to_double() * 28.0
                draw_block(x, y, g.current_kind, false)
              }
            }
          }
        }
      }
      
      if g.game_over {
        set_fill_color(0, 0, 0)
        fill_rect(board_x, board_y, 280.0, 560.0)
        
        set_fill_color(255, 23, 68)
        set_font("bold 24px Outfit")
        fill_text("GAME OVER", board_x + 65.0, board_y + 260.0)
        set_fill_color(180, 180, 200)
        set_font("14px Outfit")
        fill_text("Press Enter to Restart", board_x + 63.0, board_y + 295.0)
      }
    }
    None => ()
  }
}