package autonatv2

import (
	

	
	
	
	ma 
	
)

type MetricsTracer interface {
	CompletedRequest(EventDialRequestCompleted)
	ClientCompletedRequest([]Request, Result, error)
}

const metricNamespace = "libp2p_autonatv2"

var (
	requestsCompleted = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: metricNamespace,
			Name:      "requests_completed_total",
			Help:      "Requests Completed",
		},
		[]string{"server_error", "response_status", "dial_status", "dial_data_required", "ip_or_dns_version", "transport"},
	)
	clientRequestsCompleted = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: metricNamespace,
			Name:      "client_requests_completed_total",
			Help:      "Client Requests Completed",
		},
		[]string{"ip_or_dns_version", "transport", "addr_count", "dial_refused", "reachability"},
	)
	clientRequestsTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: metricNamespace,
			Name:      "client_requests_total",
			Help:      "Client Requests Total",
		},
		[]string{"outcome"},
	)
)

type metricsTracer struct {
}

func ( prometheus.Registerer) MetricsTracer {
	metricshelper.RegisterCollectors(, requestsCompleted, clientRequestsCompleted, clientRequestsTotal)
	return &metricsTracer{}
}

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

	 := getErrString(.Error)

	 := "false"
	if .DialDataRequired {
		 = "true"
	}

	var ,  string
	if .DialedAddr != nil {
		 = getIPOrDNSVersion(.DialedAddr)
		 = metricshelper.GetTransport(.DialedAddr)
	}

	* = append(*,
		,
		pb.DialResponse_ResponseStatus_name[int32(.ResponseStatus)],
		pb.DialStatus_name[int32(.DialStatus)],
		,
		,
		,
	)
	requestsCompleted.WithLabelValues(*...).Inc()
}

func ( *metricsTracer) ( []Request,  Result,  error) {
	 := metricshelper.GetStringSlice()
	defer metricshelper.PutStringSlice()

	if  != nil {
		clientRequestsTotal.WithLabelValues("failure").Inc()
		return
	}
	clientRequestsTotal.WithLabelValues("success").Inc()

	 := len()
	 := "false"
	if .AllAddrsRefused {
		 = "true"
	}
	 := "unknown"
	switch .Reachability {
	case network.ReachabilityPublic:
		 = "public"
	case network.ReachabilityPrivate:
		 = "private"
	}

	 := "unknown"
	 := "unknown"
	if .Addr != nil {
		 = getIPOrDNSVersion(.Addr)
		 = metricshelper.GetTransport(.Addr)
	}

	* = append(*,
		,
		,
		strconv.Itoa(),
		,
		,
	)
	clientRequestsCompleted.WithLabelValues(*...).Inc()
}

func getIPOrDNSVersion( ma.Multiaddr) string {
	if len() == 0 {
		return ""
	}
	 := "unknown"
	switch [0].Protocol().Code {
	case ma.P_DNS, ma.P_DNSADDR:
		 = "dns"
	case ma.P_DNS4:
		 = "dns4"
	case ma.P_DNS6:
		 = "dns6"
	case ma.P_IP4:
		 = "ip4"
	case ma.P_IP6:
		 = "ip6"
	}
	return 
}

func getErrString( error) string {
	var  string
	switch  {
	case nil:
		 = "nil"
	case errBadRequest, errDialDataRefused, errResourceLimitExceeded:
		 = .Error()
	default:
		 = "other"
	}
	return 
}