///|
/// Histogram family indexed by a validated positional label schema.
pub struct HistogramVec {
  descriptor : @metric.Descriptor
  schema : LabelSchema
  boundaries : Array[Double]
  children : Map[String, @metric.Histogram]
  lock : @storage.Mutex
}

///|
pub fn HistogramVec::new(
  descriptor : @metric.Descriptor,
  boundaries : Array[Double],
  cardinality_limit? : Int,
) -> HistogramVec raise VectorError {
  expect_kind(descriptor, HistogramKind)
  @metric.validate_histogram_boundaries(boundaries) catch {
    _ => raise MetricConstructionFailed(descriptor.name())
  }
  let schema = make_schema(descriptor, cardinality_limit)
  {
    descriptor,
    schema,
    boundaries: boundaries.copy(),
    children: Map([]),
    lock: @storage.Mutex::new(),
  }
}

///|
pub fn HistogramVec::descriptor(self : HistogramVec) -> @metric.Descriptor {
  self.descriptor
}

///|
pub fn HistogramVec::with_label_values(
  self : HistogramVec,
  values : Array[String],
) -> @metric.Histogram raise VectorError {
  let key = self.schema.encode_key(values)
  self.lock.lock()
  defer self.lock.unlock()
  match self.children.get(key) {
    Some(child) => child
    None => {
      ensure_capacity(self.schema.cardinality_limit(), self.children.length())
      let labels = child_labels(self.descriptor, self.schema, values)
      let child = make_histogram_child(self.descriptor, self.boundaries, labels)
      self.children[key] = child
      child
    }
  }
}

///|
pub fn HistogramVec::with_labels(
  self : HistogramVec,
  labels : Map[String, String],
) -> @metric.Histogram raise VectorError {
  self.with_label_values(self.schema.values_from_labels(labels))
}

///|
pub fn HistogramVec::delete_label_values(
  self : HistogramVec,
  values : Array[String],
) -> Bool raise VectorError {
  let key = self.schema.encode_key(values)
  self.lock.lock()
  defer self.lock.unlock()
  if !self.children.contains(key) {
    return false
  }
  self.children.remove(key)
  true
}

///|
pub fn HistogramVec::delete_labels(
  self : HistogramVec,
  labels : Map[String, String],
) -> Bool raise VectorError {
  self.delete_label_values(self.schema.values_from_labels(labels))
}

///|
pub fn HistogramVec::reset(self : HistogramVec) -> Int {
  self.lock.lock()
  defer self.lock.unlock()
  let count = self.children.length()
  self.children.clear()
  count
}

///|
pub fn HistogramVec::child_count(self : HistogramVec) -> Int {
  self.lock.lock()
  defer self.lock.unlock()
  self.children.length()
}

///|
pub fn HistogramVec::children(self : HistogramVec) -> Array[@metric.Histogram] {
  self.lock.lock()
  defer self.lock.unlock()
  self.children.values().collect()
}