package metrics

import (
	
	
	
	
)

// Family is a metric vector keyed by a fixed label set.
type Family struct {
	mu         sync.Mutex
	name       string
	typ        MetricType
	labelNames []string
	children   map[string]*FamilyMetric
}

// FamilyMetric is one labeled metric in a [Family].
type FamilyMetric struct {
	mu      sync.Mutex
	labels  []Label
	counter uint64
	gauge   float64
}

// NewFamily returns a metric family with labelNames in output order.
func ( string,  MetricType,  ...string) *Family {
	return &Family{
		name:       ,
		typ:        ,
		labelNames: append([]string(nil), ...),
		children:   make(map[string]*FamilyMetric),
	}
}

// With returns the child metric for labelValues.
func ( *Family) ( ...string) (*FamilyMetric, error) {
	if  == nil {
		return nil, errors.New("metrics: nil family")
	}
	if len() != len(.labelNames) {
		return nil, fmt.Errorf("metrics: got %d label values, want %d", len(), len(.labelNames))
	}
	 := make([]Label, len())
	for  := range  {
		[] = Label{Name: .labelNames[], Value: []}
	}
	 := familyKey()

	.mu.Lock()
	defer .mu.Unlock()
	 := .children[]
	if  == nil {
		 = &FamilyMetric{labels: }
		.children[] = 
	}
	return , nil
}

// Add adds delta to m. Use it for counter families.
func ( *FamilyMetric) ( uint64) {
	if  == nil {
		return
	}
	.mu.Lock()
	.counter += 
	.mu.Unlock()
}

// Set sets m to value. Use it for gauge families.
func ( *FamilyMetric) ( float64) {
	if  == nil {
		return
	}
	.mu.Lock()
	.gauge = 
	.mu.Unlock()
}

// StructuredSnapshot returns all children in f.
func ( *Family) () StructuredSnapshot {
	if  == nil {
		return nil
	}
	.mu.Lock()
	 := make(map[string]*FamilyMetric, len(.children))
	for ,  := range .children {
		[] = 
	}
	.mu.Unlock()

	 := make(StructuredSnapshot, len())
	for ,  := range  {
		.mu.Lock()
		 := MetricValue{
			Name:    .name,
			Type:    .typ,
			Labels:  append([]Label(nil), .labels...),
			Counter: .counter,
			Gauge:   .gauge,
		}
		.mu.Unlock()
		[.name+"\x00"+] = 
	}
	return 
}

func familyKey( []string) string {
	return strings.Join(, "\x00")
}