///|
/// N1-N2: Neutral Type Resolution
///
/// These rules resolve neutral types (B, S, WS, ON, FSI, LRI, RLI, PDI)
/// after bracket pair resolution.

///|
/// Resolve neutral types within an isolating run sequence
fn resolve_neutral_types(
  types : Array[BidiClass],
  _levels : Array[Int],
  seq : IsolatingRunSequence,
) -> Unit {
  let indices = seq.indices
  if indices.length() == 0 {
    return
  }

  // Find runs of neutrals and resolve them
  let mut i = 0
  while i < indices.length() {
    let idx = indices[i]
    let bc = types[idx]
    if is_neutral_or_isolate(bc) {
      // Found start of a neutral run
      let run_start = i

      // Find end of neutral run
      let mut run_end = i
      while run_end + 1 < indices.length() {
        let next_bc = types[indices[run_end + 1]]
        if is_neutral_or_isolate(next_bc) {
          run_end += 1
        } else {
          break
        }
      }

      // Get preceding strong type
      let preceding = get_preceding_strong_type(
        types,
        indices,
        run_start,
        seq.sos,
      )

      // Get following strong type
      let following = get_following_strong_type(
        types,
        indices,
        run_end,
        seq.eos,
      )

      // N1: If preceding and following are same type, neutrals become that type
      // N2: Otherwise, neutrals become embedding direction
      let resolved : BidiClass = match preceding {
        L if following is L => BidiClass::L
        R if following is R => BidiClass::R
        _ => if seq.level % 2 == 0 { BidiClass::L } else { BidiClass::R }
      }

      // Apply resolved type to all neutrals in the run
      for j = run_start; j <= run_end; j = j + 1 {
        types[indices[j]] = resolved
      }
      i = run_end + 1
    } else {
      i += 1
    }
  }
}

///|
/// Check if type is neutral or isolate (for N rules)
fn is_neutral_or_isolate(bc : BidiClass) -> Bool {
  match bc {
    B | S | WS | ON | LRI | RLI | FSI | PDI => true
    _ => false
  }
}

///|
/// Get the preceding strong type in the sequence
/// Returns effective strong type (L, R) - EN and AN become R
fn get_preceding_strong_type(
  types : Array[BidiClass],
  indices : Array[Int],
  before_pos : Int,
  sos : BidiClass,
) -> BidiClass {
  let mut i = before_pos - 1
  while i >= 0 {
    let bc = types[indices[i]]
    match bc {
      L => return BidiClass::L
      R => return BidiClass::R
      EN | AN => return BidiClass::R // EN and AN are treated as R
      _ => i -= 1
    }
  }
  sos
}

///|
/// Get the following strong type in the sequence
/// Returns effective strong type (L, R) - EN and AN become R
fn get_following_strong_type(
  types : Array[BidiClass],
  indices : Array[Int],
  after_pos : Int,
  eos : BidiClass,
) -> BidiClass {
  let mut i = after_pos + 1
  while i < indices.length() {
    let bc = types[indices[i]]
    match bc {
      L => return BidiClass::L
      R => return BidiClass::R
      EN | AN => return BidiClass::R // EN and AN are treated as R
      _ => i += 1
    }
  }
  eos
}