///|
pub(all) struct LamportClock {
  node : String
  counter : Int
}

///|
pub fn LamportClock::new(node : String) -> LamportClock {
  { node, counter: 0 }
}

///|
pub fn LamportClock::tick(self : LamportClock) -> LamportClock {
  { ..self, counter: self.counter + 1 }
}

///|
pub fn LamportClock::observe(
  self : LamportClock,
  remote_counter : Int,
) -> LamportClock {
  let next = if remote_counter > self.counter {
    remote_counter
  } else {
    self.counter
  }
  { ..self, counter: next + 1 }
}

///|
pub fn LamportClock::event(
  self : LamportClock,
  id : String,
  payload : String,
) -> CausalEvent {
  let next = self.tick()
  CausalEvent::new(
    id,
    self.node,
    VectorClock::new().set(self.node, next.counter),
    payload,
  )
}