///|
pub(all) struct ConflictDetector {
  hostile_matrix : HostileMatrix
  topology_matrix : HostileMatrix
} derive(Debug)

///|
pub fn ConflictDetector::new(
  table : @interlocking.InterlockingTable,
) -> ConflictDetector {
  let hm = HostileMatrix::build_from_interlocking_table(table)
  let tm = HostileMatrix::build_topological_conflict_table(table)
  { hostile_matrix: hm, topology_matrix: tm }
}

///|
pub fn ConflictDetector::is_route_allowed(
  self : ConflictDetector,
  table : @interlocking.InterlockingTable,
  candidate_route_id : @interlocking.RouteId,
) -> Result[Unit, String] {
  // 1. Bitmask fast check against active routes
  let active_mask = RouteBitSet::empty()
  for r_id_int, _ in table.active_routes {
    if table.is_route_reserved(@interlocking.RouteId::new(r_id_int)) {
      active_mask.set(r_id_int)
    }
  }

  if self.hostile_matrix.is_conflict_with_active_mask(
      candidate_route_id, active_mask,
    ) {
    return Err("Fast Bitmask Rejection: Hostile route is currently active!")
  }

  // 2. Detailed dynamic topological check
  match table.get_rule(candidate_route_id) {
    None => Err("Candidate route rule not found")
    Some(candidate_rule) => {
      for _, active_state in table.active_routes {
        if !table.is_route_reserved(active_state.rule.id) {
          continue
        }
        let active_rule = active_state.rule
        match detect_topological_conflicts(candidate_rule, active_rule) {
          Some(conflict) =>
            return Err(
              "Topological Conflict (" +
              conflict.conflict_type +
              "): " +
              conflict.conflicting_element,
            )
          None => ()
        }
      }
      Ok(())
    }
  }
}

///|
pub fn ConflictDetector::is_route_allowed_fast(
  self : ConflictDetector,
  table : @interlocking.InterlockingTable,
  candidate_route_id : @interlocking.RouteId,
) -> Bool {
  let active_mask = RouteBitSet::empty()
  for r_id_int, _ in table.active_routes {
    if table.is_route_reserved(@interlocking.RouteId::new(r_id_int)) {
      active_mask.set(r_id_int)
    }
  }
  !self.hostile_matrix.is_conflict_with_active_mask(
    candidate_route_id, active_mask,
  ) &&
  !self.topology_matrix.is_conflict_with_active_mask(
    candidate_route_id, active_mask,
  )
}