// ============================================================
// Blackboard inspection and composition APIs
//
// These helpers keep integration code from reaching into the map directly.
// They are useful for save games, debugging panels, simulation isolation, and
// deterministic test fixtures.
// ============================================================

///|
/// Read a value without committing to a concrete value type.
pub fn Blackboard::get_value(self : Blackboard, key : String) -> Value? {
  self.data.get(key)
}

///|
/// Store a previously captured value.
pub fn Blackboard::set_value(
  self : Blackboard,
  key : String,
  value : Value,
) -> Unit {
  self.data.set(key, value)
}

///|
/// Insert a value only when the key does not already exist.
pub fn Blackboard::set_if_absent(
  self : Blackboard,
  key : String,
  value : Value,
) -> Bool {
  if self.data.contains(key) {
    false
  } else {
    self.data.set(key, value)
    true
  }
}

///|
/// Return keys in the map's stable insertion order.
pub fn Blackboard::keys(self : Blackboard) -> Array[String] {
  let result : Array[String] = []
  self.data.each(fn(key, _) { result.push(key) })
  result
}

///|
/// Return the number of active nested snapshots.
pub fn Blackboard::snapshot_depth(self : Blackboard) -> Int {
  self.snapshots.length()
}

///|
/// Copy all values from another blackboard into this one.
pub fn Blackboard::merge(self : Blackboard, other : Blackboard) -> Unit {
  other.data.each(fn(key, value) { self.data.set(key, value) })
}

///|
/// Create an independent blackboard copy without copying snapshot history.
pub fn Blackboard::clone(self : Blackboard) -> Blackboard {
  let copy = Blackboard::new()
  copy.merge(self)
  copy
}

///|
/// Convert a Value into a stable type label for diagnostics.
pub fn Value::type_name(self : Value) -> String {
  match self {
    Value::Bool(_) => "bool"
    Value::Int(_) => "int"
    Value::Double(_) => "double"
    Value::Str(_) => "string"
  }
}