package eventbus

import (
	
	

	

	
)

const metricNamespace = "libp2p_eventbus"

var (
	eventsEmitted = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: metricNamespace,
			Name:      "events_emitted_total",
			Help:      "Events Emitted",
		},
		[]string{"event"},
	)
	totalSubscribers = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: metricNamespace,
			Name:      "subscribers_total",
			Help:      "Number of subscribers for an event type",
		},
		[]string{"event"},
	)
	subscriberQueueLength = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: metricNamespace,
			Name:      "subscriber_queue_length",
			Help:      "Subscriber queue length",
		},
		[]string{"subscriber_name"},
	)
	subscriberQueueFull = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: metricNamespace,
			Name:      "subscriber_queue_full",
			Help:      "Subscriber Queue completely full",
		},
		[]string{"subscriber_name"},
	)
	subscriberEventQueued = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: metricNamespace,
			Name:      "subscriber_event_queued",
			Help:      "Event Queued for subscriber",
		},
		[]string{"subscriber_name"},
	)
	collectors = []prometheus.Collector{
		eventsEmitted,
		totalSubscribers,
		subscriberQueueLength,
		subscriberQueueFull,
		subscriberEventQueued,
	}
)

// MetricsTracer tracks metrics for the eventbus subsystem
type MetricsTracer interface {

	// EventEmitted counts the total number of events grouped by event type
	EventEmitted(typ reflect.Type)

	// AddSubscriber adds a subscriber for the event type
	AddSubscriber(typ reflect.Type)

	// RemoveSubscriber removes a subscriber for the event type
	RemoveSubscriber(typ reflect.Type)

	// SubscriberQueueLength is the length of the subscribers channel
	SubscriberQueueLength(name string, n int)

	// SubscriberQueueFull tracks whether a subscribers channel if full
	SubscriberQueueFull(name string, isFull bool)

	// SubscriberEventQueued counts the total number of events grouped by subscriber
	SubscriberEventQueued(name string)
}

type metricsTracer struct{}

var _ MetricsTracer = &metricsTracer{}

type metricsTracerSetting struct {
	reg prometheus.Registerer
}

type MetricsTracerOption func(*metricsTracerSetting)

func ( prometheus.Registerer) MetricsTracerOption {
	return func( *metricsTracerSetting) {
		if  != nil {
			.reg = 
		}
	}
}

func ( ...MetricsTracerOption) MetricsTracer {
	 := &metricsTracerSetting{reg: prometheus.DefaultRegisterer}
	for ,  := range  {
		()
	}
	metricshelper.RegisterCollectors(.reg, collectors...)
	return &metricsTracer{}
}

func ( *metricsTracer) ( reflect.Type) {
	 := metricshelper.GetStringSlice()
	defer metricshelper.PutStringSlice()

	* = append(*, strings.TrimPrefix(.String(), "event."))
	eventsEmitted.WithLabelValues(*...).Inc()
}

func ( *metricsTracer) ( reflect.Type) {
	 := metricshelper.GetStringSlice()
	defer metricshelper.PutStringSlice()

	* = append(*, strings.TrimPrefix(.String(), "event."))
	totalSubscribers.WithLabelValues(*...).Inc()
}

func ( *metricsTracer) ( reflect.Type) {
	 := metricshelper.GetStringSlice()
	defer metricshelper.PutStringSlice()

	* = append(*, strings.TrimPrefix(.String(), "event."))
	totalSubscribers.WithLabelValues(*...).Dec()
}

func ( *metricsTracer) ( string,  int) {
	 := metricshelper.GetStringSlice()
	defer metricshelper.PutStringSlice()

	* = append(*, )
	subscriberQueueLength.WithLabelValues(*...).Set(float64())
}

func ( *metricsTracer) ( string,  bool) {
	 := metricshelper.GetStringSlice()
	defer metricshelper.PutStringSlice()

	* = append(*, )
	 := subscriberQueueFull.WithLabelValues(*...)
	if  {
		.Set(1)
	} else {
		.Set(0)
	}
}

func ( *metricsTracer) ( string) {
	 := metricshelper.GetStringSlice()
	defer metricshelper.PutStringSlice()

	* = append(*, )
	subscriberEventQueued.WithLabelValues(*...).Inc()
}