///|
pub(all) struct CausalPair {
  left : String
  right : String
  order : CausalOrder
}

///|
pub fn CausalPair::new(
  left : String,
  right : String,
  order : CausalOrder,
) -> CausalPair {
  { left, right, order }
}

///|
pub fn compare_events(left : CausalEvent, right : CausalEvent) -> CausalPair {
  CausalPair::new(left.id, right.id, left.clock.compare(right.clock))
}

///|
pub fn find_concurrent_pairs(events : Array[CausalEvent]) -> Array[CausalPair] {
  let pairs = []
  for i = 0; i < events.length(); i = i + 1 {
    for j = i + 1; j < events.length(); j = j + 1 {
      let pair = compare_events(events[i], events[j])
      if pair.order == Concurrent {
        pairs.push(pair)
      }
    }
  }
  pairs
}

///|
pub fn causal_frontier(events : Array[CausalEvent]) -> VectorClock {
  let mut frontier = VectorClock::new()
  for event in events {
    frontier = frontier.merge(event.clock)
  }
  frontier
}