///|
/// A metric that may increase or decrease.
pub struct Gauge {
  descriptor : Descriptor
  value : @storage.ScalarCell
}

///|
pub fn Gauge::new(
  name : String,
  help? : String = "",
  unit? : String,
  const_labels? : Array[Label] = [],
) -> Gauge raise MetricError {
  let descriptor = make_metric_descriptor(
    name,
    GaugeKind,
    help,
    unit,
    const_labels,
  )
  { descriptor, value: @storage.ScalarCell::new(0.0) }
}

///|
pub fn Gauge::name(self : Gauge) -> String {
  self.descriptor.name()
}

///|
pub fn Gauge::help(self : Gauge) -> String {
  self.descriptor.help()
}

///|
pub fn Gauge::unit(self : Gauge) -> String? {
  self.descriptor.unit()
}

///|
pub fn Gauge::labels(self : Gauge) -> Array[Label] {
  self.descriptor.const_labels()
}

///|
pub fn Gauge::descriptor(self : Gauge) -> Descriptor {
  self.descriptor
}

///|
pub fn Gauge::set(self : Gauge, value : Double) -> Unit {
  self.value.set(value)
}

///|
pub fn Gauge::add(self : Gauge, delta : Double) -> Unit {
  self.value.add(delta)
}

///|
pub fn Gauge::sub(self : Gauge, delta : Double) -> Unit {
  self.value.add(-delta)
}

///|
pub fn Gauge::inc(self : Gauge) -> Unit {
  self.value.add(1.0)
}

///|
pub fn Gauge::dec(self : Gauge) -> Unit {
  self.value.add(-1.0)
}

///|
pub fn Gauge::get(self : Gauge) -> Double {
  self.value.get()
}

///|
pub fn Gauge::snapshot(self : Gauge) -> ScalarMetricSnapshot {
  { value: self.value.get() }
}