package stats

import (
	"sync"

	"github.com/go-gost/core/observer"
	"github.com/go-gost/core/observer/stats"
	xstats "github.com/go-gost/x/observer/stats"
)

type HandlerStats struct {
	service      string
	stats        map[string]stats.Stats
	resetTraffic bool
	mu           sync.RWMutex
}

func NewHandlerStats(service string, resetTraffic bool) *HandlerStats {
	return &HandlerStats{
		service:      service,
		stats:        make(map[string]stats.Stats),
		resetTraffic: resetTraffic,
	}
}

func (p *HandlerStats) Stats(client string) stats.Stats {
	if p == nil {
		return nil
	}

	p.mu.RLock()
	pstats := p.stats[client]
	p.mu.RUnlock()
	if pstats != nil {
		return pstats
	}

	p.mu.Lock()
	defer p.mu.Unlock()
	pstats = p.stats[client]
	if pstats == nil {
		pstats = xstats.NewStats(p.resetTraffic)
	}
	p.stats[client] = pstats

	return pstats
}

func (p *HandlerStats) Events() (events []observer.Event) {
	if p == nil {
		return
	}

	p.mu.RLock()
	defer p.mu.RUnlock()

	for k, v := range p.stats {
		if !v.IsUpdated() {
			continue
		}
		events = append(events, xstats.StatsEvent{
			Kind:         "handler",
			Service:      p.service,
			Client:       k,
			TotalConns:   v.Get(stats.KindTotalConns),
			CurrentConns: v.Get(stats.KindCurrentConns),
			InputBytes:   v.Get(stats.KindInputBytes),
			OutputBytes:  v.Get(stats.KindOutputBytes),
			TotalErrs:    v.Get(stats.KindTotalErrs),
		})
	}
	return
}
