using selfhost.vm.boxes.json_cur as MiniJsonCur
using selfhost.shared.common.mini_vm_scan as MiniVmScan

static box MiniVmBinOp {
  // Minimal: Print(BinaryOp) with operator "+"; supports string+string and int+int
  try_print_binop_at(json, end, print_pos) {
    local scan = new MiniVmScan()
    local k_bo = "\"kind\":\"BinaryOp\""
    local bpos = scan.index_of_from(json, k_bo, print_pos)
    if bpos <= 0 || bpos >= end { return -1 }
    // bound BinaryOp object (prefer expression object)
    local k_expr = "\"expression\":{"
    local expr_pos = scan.index_of_from(json, k_expr, print_pos)
    local obj_start = -1
    if expr_pos > 0 && expr_pos < end {
      obj_start = scan.index_of_from(json, "{", expr_pos)
    } else {
      obj_start = scan.index_of_from(json, "{", bpos)
    }
    local obj_end = scan.find_balanced_object_end(json, obj_start)
    if obj_start <= 0 || obj_end <= 0 || obj_end > end { return -1 }
    // operator must be '+'
    local k_op = "\"operator\":\"+\""
    local opos = scan.index_of_from(json, k_op, bpos)
    if opos <= 0 || opos >= obj_end { return -1 }

    // string + string fast-path
    local cur = new MiniJson()
    local k_left_lit = "\"left\":{\"kind\":\"Literal\""
    local lhdr = scan.index_of_from(json, k_left_lit, opos)
    if lhdr > 0 && lhdr < obj_end {
      local k_sval = "\"value\":\""
      local lvp = scan.index_of_from(json, k_sval, lhdr)
      if lvp > 0 && lvp < obj_end {
        local li = lvp + k_sval.length()
        local lval = cur.read_quoted_from(json, li)
        if lval {
          local k_right_lit = "\"right\":{\"kind\":\"Literal\""
          local rhdr = scan.index_of_from(json, k_right_lit, li + lval.length())
          if rhdr > 0 && rhdr < obj_end {
            local rvp = scan.index_of_from(json, k_sval, rhdr)
            if rvp > 0 && rvp < obj_end {
              local ri = rvp + k_sval.length()
              local rval = cur.read_quoted_from(json, ri)
              if rval { print(lval + rval)  return ri + rval.length() + 1 }
            }
          }
        }
      }
    }
    // int + int typed pattern
    local k_l = "\"left\":{\"kind\":\"Literal\""
    local lpos = scan.index_of_from(json, k_l, opos)
    if lpos <= 0 || lpos >= obj_end { return -1 }
    local k_lint = "\"left\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":"
    local li2 = scan.index_of_from(json, k_lint, opos)
    if li2 <= 0 || li2 >= obj_end { return -1 }
    local ldigits = scan.read_digits(json, li2 + k_lint.length())
    if ldigits == "" { return -1 }
    local k_r = "\"right\":{\"kind\":\"Literal\""
    local rpos = scan.index_of_from(json, k_r, lpos)
    if rpos <= 0 || rpos >= obj_end { return -1 }
    local k_rint = "\"right\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":"
    local ri2 = scan.index_of_from(json, k_rint, lpos)
    if ri2 <= 0 || ri2 >= obj_end { return -1 }
    local rdigits = scan.read_digits(json, ri2 + k_rint.length())
    if rdigits == "" { return -1 }
    local ai = scan._str_to_int(ldigits)
    local bi = scan._str_to_int(rdigits)
    print(scan._int_to_str(ai + bi))
    return obj_end + 1
  }

  // Greedy disabled (kept for parity)
  try_print_binop_int_greedy(json, end, print_pos) { return -1 }

  // Fallback: within the current Print's expression BinaryOp object, scan for two numeric values and sum
  try_print_binop_sum_any(json, end, print_pos) {
    local scan = new MiniVmScan()
    local k_expr = "\"expression\":{"
    local expr_pos = scan.index_of_from(json, k_expr, print_pos)
    // If expression object cannot be bounded, fall back to typed-direct pattern within the current slice
    if expr_pos <= 0 || expr_pos >= end {
      // bound coarse slice to current Print by next Print marker
      local k_print = "\"kind\":\"Print\""
      local next_p = scan.index_of_from(json, k_print, print_pos + 1)
      local slice_end = end
      if next_p > 0 { slice_end = next_p }
      local k_lint = "\"left\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":"
      local k_rint = "\"right\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":"
      // only if BinaryOp is present in this slice
      if scan.index_of_from(json, "\"kind\":\"BinaryOp\"", print_pos) > 0 {
      local lp = scan.index_of_from(json, k_lint, print_pos)
      if lp > 0 { if lp < slice_end {
        local ld = scan.read_digits(json, lp + k_lint.length())
        if ld != "" {
          local rp = scan.index_of_from(json, k_rint, lp + k_lint.length())
          if rp > 0 { if rp < slice_end {
            local rd = scan.read_digits(json, rp + k_rint.length())
            if rd != "" { print(scan._int_to_str(scan._str_to_int(ld) + scan._str_to_int(rd)))  return 1 }
          }}
        }
      }}
      }
      return -1
    }
    local obj_start = scan.index_of_from(json, "{", expr_pos)
    if obj_start <= 0 || obj_start >= end { return -1 }
    local obj_end = scan.find_balanced_object_end(json, obj_start)
    if obj_end <= 0 || obj_end > end {
      local k_print = "\"kind\":\"Print\""
      local next_p = scan.index_of_from(json, k_print, print_pos + 1)
      local obj_end2 = end
      if next_p > 0 && next_p <= end { obj_end2 = next_p }
      // typed-direct fallback in bounded region
      local k_lint = "\"left\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":"
      local k_rint = "\"right\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":"
      local lp = scan.index_of_from(json, k_lint, obj_start)
      if lp > 0 { if lp < obj_end2 {
        local ld = scan.read_digits(json, lp + k_lint.length())
        if ld != "" {
          local rp = scan.index_of_from(json, k_rint, lp + k_lint.length())
          if rp > 0 { if rp < obj_end2 {
            local rd = scan.read_digits(json, rp + k_rint.length())
            if rd != "" { print(scan._int_to_str(scan._str_to_int(ld) + scan._str_to_int(rd)))  return 1 }
          }}
        }
      }}
      return -1
    }
    local k_bo = "\"kind\":\"BinaryOp\""
    local bpos = scan.index_of_from(json, k_bo, obj_start)
    if bpos <= 0 || bpos >= obj_end {
      // typed-direct fallback (within bounds window)
      local k_lint = "\"left\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":"
      local k_rint = "\"right\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":"
      local lp = scan.index_of_from(json, k_lint, obj_start)
      if lp > 0 { if lp < obj_end {
        local ld = scan.read_digits(json, lp + k_lint.length())
        if ld != "" {
          local rp = scan.index_of_from(json, k_rint, lp + k_lint.length())
          if rp > 0 { if rp < obj_end {
            local rd = scan.read_digits(json, rp + k_rint.length())
            if rd != "" { print(scan._int_to_str(scan._str_to_int(ld) + scan._str_to_int(rd)))  return 1 }
          }}
        }
      }}
      return -1
    }
    local k_plus = "\"operator\":\"+\""
    local opos = scan.index_of_from(json, k_plus, bpos)
    if opos <= 0 || opos >= obj_end {
      // typed-direct fallback
      local k_lint = "\"left\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":"
      local k_rint = "\"right\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":"
      local lp = scan.index_of_from(json, k_lint, obj_start)
      if lp > 0 { if lp < obj_end {
        local ld = scan.read_digits(json, lp + k_lint.length())
        if ld != "" {
          local rp = scan.index_of_from(json, k_rint, lp + k_lint.length())
          if rp > 0 { if rp < obj_end {
            local rd = scan.read_digits(json, rp + k_rint.length())
            if rd != "" { print(scan._int_to_str(scan._str_to_int(ld) + scan._str_to_int(rd)))  return 1 }
          }}
        }
      }}
      return -1
    }
    local nums = []
    local i = obj_start
    loop (i < obj_end) {
      if json.substring(i, i+1) == "\"" {
        local j = scan.index_of_from(json, "\"", i+1)
        if j < 0 || j >= obj_end { break }
        i = j + 1
        continue
      }
      local d = scan.read_digits(json, i)
      if d { nums.push(d)  i = i + d.length()  continue }
      i = i + 1
    }
    local nsz = nums.length()
    if nsz < 2 { return -1 }
    local a = scan._str_to_int(nums.get(nsz-2))
    local b = scan._str_to_int(nums.get(nsz-1))
    print(scan._int_to_str(a + b))
    return obj_end + 1
  }

  // Deterministic: within Print.expression BinaryOp('+'), pick two successive 'value' fields and sum
  try_print_binop_sum_expr_values(json, end, print_pos) {
    local scan = new MiniVmScan()
    local cur = new MiniJson()
    local k_expr = "\"expression\":{"
    local expr_pos = scan.index_of_from(json, k_expr, print_pos)
    if expr_pos <= 0 || expr_pos >= end { return -1 }
    local obj_start = scan.index_of_from(json, "{", expr_pos)
    if obj_start <= 0 || obj_start >= end { return -1 }
    local obj_end = scan.find_balanced_object_end(json, obj_start)
    if obj_end <= 0 || obj_end > end { return -1 }
    local k_bo = "\"kind\":\"BinaryOp\""
    local bpos = scan.index_of_from(json, k_bo, obj_start)
    if bpos <= 0 || bpos >= obj_end { return -1 }
    local k_plus = "\"operator\":\"+\""
    local opos = scan.index_of_from(json, k_plus, bpos)
    if opos <= 0 || opos >= obj_end { return -1 }
    local k_v = "\"value\":"
    local found = 0
    local a = 0
    local pos = scan.index_of_from(json, k_v, obj_start)
    loop (pos > 0 && pos < obj_end) {
      local di = cur.read_digits_from(json, pos + k_v.length())
      if di != "" {
        if found == 0 { a = scan._str_to_int(di)  found = 1 } else {
          local b = scan._str_to_int(di)
          print(scan._int_to_str(a + b))
          return obj_end + 1
        }
      }
      pos = scan.index_of_from(json, k_v, pos + k_v.length())
      if pos <= 0 || pos >= obj_end { break }
    }
    return -1
  }

  // Simpler: after operator '+', scan two successive 'value' fields and sum
  try_print_binop_sum_after_bop(json) {
    local scan = new MiniVmScan()
    local k_bo = "\"kind\":\"BinaryOp\""
    local bpos = json.indexOf(k_bo)
    if bpos < 0 { return -1 }
    local k_plus = "\"operator\":\"+\""
    local opos = scan.index_of_from(json, k_plus, bpos)
    if opos < 0 { return -1 }
    local k_v = "\"value\":"
    local p = opos
    p = scan.index_of_from(json, k_v, p)
    if p < 0 { return -1 }
    p = scan.index_of_from(json, k_v, p + k_v.length())
    if p < 0 { return -1 }
    local end1 = scan.index_of_from(json, "}", p)
    if end1 < 0 { return -1 }
    local d1 = scan.read_digits(json, p + k_v.length())
    if d1 == "" { return -1 }
    p = scan.index_of_from(json, k_v, end1)
    if p < 0 { return -1 }
    p = scan.index_of_from(json, k_v, p + k_v.length())
    if p < 0 { return -1 }
    local end2 = scan.index_of_from(json, "}", p)
    if end2 < 0 { return -1 }
    local d2 = scan.read_digits(json, p + k_v.length())
    if d2 == "" { return -1 }
    local ai = scan._str_to_int(d1)
    local bi = scan._str_to_int(d2)
    print(scan._int_to_str(ai + bi))
    return 0
  }

  // Fallback: find first BinaryOp and return sum of two numeric values as string
  parse_first_binop_sum(json) {
    local scan = new MiniVmScan()
    local k_bo = "\"kind\":\"BinaryOp\""
    local bpos = json.indexOf(k_bo)
    if bpos < 0 { return "" }
    local k_typed = "\"type\":\"int\",\"value\":"
    local p1 = scan.index_of_from(json, k_typed, bpos)
    if p1 < 0 { return "" }
    local d1 = scan.read_digits(json, p1 + k_typed.length())
    if d1 == "" { return "" }
    local p2 = scan.index_of_from(json, k_typed, p1 + k_typed.length())
    if p2 < 0 { return "" }
    local d2 = scan.read_digits(json, p2 + k_typed.length())
    if d2 == "" { return "" }
    return scan._int_to_str(scan._str_to_int(d1) + scan._str_to_int(d2))
  }
}
