// terminator_handler.hako — Phase 1 Day 3: Terminator処理
// Strategy: 箱化モジュール化 - Ret/Jump/Branch を分離

using selfhost.shared.common.string_helpers as StringHelpers
using selfhost.shared.common.string_ops as StringOps
using selfhost.vm.boxes.result_box as Result
using selfhost.vm.hakorune-vm.instrs_locator as InstrsLocatorBox
using selfhost.vm.hakorune-vm.backward_object_scanner as BackwardObjectScannerBox
using selfhost.vm.hakorune-vm.core_bridge_ops as CoreBridgeOps

static box TerminatorHandlerBox {
  // Execute terminator instruction and return next action
  // Returns: Result.Ok(MapBox with "type" and other fields) or Result.Err(message)
  //
  // Return types:
  //   - "ret": {"type": "ret", "value": <return_value>}
  //   - "jump": {"type": "jump", "next_bb": <target_block_id>}
  //   - "branch": {"type": "branch", "next_bb": <selected_block_id>}
  handle_terminator(block_json, regs) {
    // Find terminator field
    local key_term = "\"terminator\":{"
    local term_start = block_json.indexOf(key_term)
    if term_start < 0 {
      // No terminator (should not happen in valid MIR)
      return Result.Err("terminator not found")
    }

    local term_json_start = term_start + key_term.length() - 1
    local term_end = me._find_terminator_end(block_json, term_json_start)
    if term_end < 0 {
      return Result.Err("terminator end not found")
    }

    local term_json = block_json.substring(term_json_start, term_end + 1)

    // Extract op field (tolerant: ':' + optional spaces)
    local key_opk = "\"op\""
    local pos = term_json.indexOf(key_opk)
    if pos < 0 {
      // fallback
      local fb = me._fallback_handle(block_json, regs)
      if fb.is_Ok() { return fb }
      return Result.Err("terminator op not found")
    }
    pos = pos + key_opk.length()
    // find ':' then skip whitespace
    loop(pos < term_json.length()) {
      local ch = term_json.substring(pos, pos+1)
      if ch == ":" { pos = pos + 1  break }
      if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { pos = pos + 1  continue }
      local fb = me._fallback_handle(block_json, regs)
      if fb.is_Ok() { return fb }
      return Result.Err("terminator op colon not found")
    }
    loop(pos < term_json.length()) {
      local ch = term_json.substring(pos, pos+1)
      if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { pos = pos + 1  continue }
      break
    }
    if term_json.substring(pos, pos+1) != "\"" {
      local fb = me._fallback_handle(block_json, regs)
      if fb.is_Ok() { return fb }
      return Result.Err("terminator op quote not found")
    }
    local op_end = StringOps.index_of_from(term_json, "\"", pos+1)
    if op_end < 0 {
      local fb = me._fallback_handle(block_json, regs)
      if fb.is_Ok() { return fb }
      return Result.Err("terminator op end not found")
    }
    local op = term_json.substring(pos+1, op_end)

    // Dispatch terminator type
    if op == "ret" {
      return me._handle_ret(term_json, regs)
    }

    if op == "jump" {
      return me._handle_jump(term_json)
    }

    if op == "branch" {
      return me._handle_branch(term_json, regs)
    }

    return Result.Err("unknown terminator op: " + op)
  }

  // Fallback helper
  _fallback_handle(block_json, regs) {
    local loc = InstrsLocatorBox.locate(block_json)
    if loc.is_Err() { return loc }
    local meta = loc.as_Ok()
    local insts = meta.get("content")
    if insts == "" { return Result.Err("terminator not found") }
    local single = meta.get("single")
    local term_json = null
    if single != null && single == 1 { term_json = insts } else {
      local last = BackwardObjectScannerBox.scan_last_object(insts, 200000)
      if last.is_Err() { return Result.Err("terminator scan failed: " + last.as_Err()) }
      term_json = last.as_Ok()
    }
    local k = "\"op\""
    local p = term_json.indexOf(k)
    if p < 0 { return Result.Err("terminator op not found") }
    p = p + k.length()
    loop(p < term_json.length()) { local ch = term_json.substring(p,p+1) if ch == ":" { p = p + 1 break } if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { p = p + 1 continue } return Result.Err("terminator op colon not found") }
    loop(p < term_json.length()) { local ch = term_json.substring(p,p+1) if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { p = p + 1 continue } break }
    if term_json.substring(p,p+1) != "\"" { return Result.Err("terminator op quote not found") }
    local e = StringOps.index_of_from(term_json, "\"", p+1)
    if e < 0 { return Result.Err("terminator op end not found") }
    local op = term_json.substring(p+1, e)
    if op == "ret" { return me._handle_ret(term_json, regs) }
    if op == "jump" { return me._handle_jump(term_json) }
    if op == "branch" { return me._handle_branch(term_json, regs) }
    return Result.Err("unknown terminator op")
  }

  // Ret terminator
  _handle_ret(term_json, regs) {
    local result_map = new MapBox()
    result_map.set("type", "ret")

    // Extract value field (optional)
    local key_val = "\"value\":"
    local val_start = term_json.indexOf(key_val)
    if val_start < 0 {
      // No value → return 0
      result_map.set("value", 0)
      return Result.Ok(result_map)
    }
    val_start = val_start + key_val.length()

    local val_digits = StringHelpers.read_digits(term_json, val_start)
    if val_digits == "" {
      return Result.Err("ret: invalid value")
    }

    local val_id = StringHelpers.to_i64(val_digits)
    local reg_key = StringHelpers.int_to_str(val_id)

    // Unified behavior: get() -> null if missing
    local val = regs.get(reg_key)
    if val == null {
      val = 0
    }

    result_map.set("value", val)
    return Result.Ok(result_map)
  }

  // Jump terminator
  _handle_jump(term_json) {
    local r = CoreBridgeOps.select_jump_next_from_terminator(term_json)
    if r.is_Err() { return r }
    local next_bb = r.as_Ok()
    local result_map = new MapBox(); result_map.set("type","jump"); result_map.set("next_bb", next_bb)
    return Result.Ok(result_map)
  }

  // Branch terminator
  _handle_branch(term_json, regs) {
    local r = CoreBridgeOps.select_branch_next_from_terminator(term_json, regs)
    if r.is_Err() { return r }
    local next_bb = r.as_Ok()
    local result_map = new MapBox(); result_map.set("type","branch"); result_map.set("next_bb", next_bb)
    return Result.Ok(result_map)
  }

  // Helper: find terminator object end
  _find_terminator_end(json, start) {
    local depth = 0
    local pos = start
    local len = json.length()

    loop(pos < len) {
      local ch = json.substring(pos, pos + 1)

      if ch == "{" {
        depth = depth + 1
      }

      if ch == "}" {
        depth = depth - 1
        if depth == 0 {
          return pos
        }
      }

      pos = pos + 1
    }

    return -1
  }
}
