package daemonmetrics

import (
	"a.yandex-team.ru/library/go/core/metrics/solomon"
	"a.yandex-team.ru/library/go/yandex/solomon/reporters/puller/httppuller"
	"net/http"
	"sync/atomic"
)

type IMetrics interface {
	GetSolomonHTTPHandler() http.Handler
	ReportExecTimeMs(string, float64)
	ReportIPv4SetSize(int64)
	ReportIPv6SetSize(int64)
	ReportCbbIPAdded()
	ReportCbbBadResponse()
	ReportCbbHTTPError()
	ReportIP4TablesDrops(int64)
	ReportIP6TablesDrops(int64)
	Flush()
}

type Metrics struct {
	registry            *solomon.Registry
	ipv4DroppedPackages int64
	ipv6DroppedPackages int64
}

func (metrics *Metrics) Flush() {
	metrics.Set("cbbHTTPErrors", 0)
	metrics.Set("cbbBadResponse", 0)
	metrics.Set("cbbIpsAdded", 0)
}

func (metrics *Metrics) GetSolomonHTTPHandler() http.Handler {
	return httppuller.NewHandler(metrics.GetRegistry(), httppuller.WithSpack())
}

func (metrics *Metrics) GetRegistry() *solomon.Registry {
	return metrics.registry
}

func (metrics *Metrics) Inc(name string) {
	metrics.GetRegistry().Gauge(name).Add(1)
}

func (metrics *Metrics) Set(name string, val float64) {
	metrics.GetRegistry().Gauge(name).Set(val)
}

func (metrics *Metrics) ReportExecTimeMs(name string, val float64) {
	metrics.Set(name, val)
}

func New() *Metrics {
	metrics := Metrics{}
	opts := solomon.NewRegistryOpts().
		SetSeparator(rune('_')).
		SetPrefix("ipsetdaemon")

	metrics.registry = solomon.NewRegistry(opts)
	return &metrics
}

func (metrics *Metrics) ReportIP4TablesDrops(x int64) {
	old := atomic.SwapInt64(&metrics.ipv4DroppedPackages, x)
	if old <= x {
		metrics.Set("Ipv4TablesDrops", float64(x-old))
	} else {
		metrics.Set("Ipv4TablesDrops", float64(0))
	}
}

func (metrics *Metrics) ReportIP6TablesDrops(x int64) {
	old := atomic.SwapInt64(&metrics.ipv6DroppedPackages, x)
	if old <= x {
		metrics.Set("Ipv6TablesDrops", float64(x-old))
	} else {
		metrics.Set("Ipv6TablesDrops", float64(0))
	}
}

func (metrics *Metrics) ReportCbbHTTPError() {
	metrics.Inc("cbbHTTPErrors")
}

func (metrics *Metrics) ReportCbbBadResponse() {
	metrics.Inc("cbbBadResponse")
}

func (metrics *Metrics) ReportCbbIPAdded() {
	metrics.Inc("cbbIpsAdded")
}

func (metrics *Metrics) ReportIPv4SetSize(x int64) {
	metrics.Set("ipv4SetSize", float64(x))
}

func (metrics *Metrics) ReportIPv6SetSize(x int64) {
	metrics.Set("ipv6SetSize", float64(x))
}
