package utils

import (
	"time"

	"github.com/yusing/go-proxy/internal/task"
	"go.uber.org/atomic"
)

var (
	TimeNow           = DefaultTimeNow
	shouldCallTimeNow atomic.Bool
	timeNowTicker     = time.NewTicker(shouldCallTimeNowInterval)
	lastTimeNow       = time.Now()
)

const shouldCallTimeNowInterval = 100 * time.Millisecond

func MockTimeNow(t time.Time) {
	TimeNow = func() time.Time {
		return t
	}
}

// DefaultTimeNow is a time.Now wrapper that reduces the number of calls to time.Now
// by caching the result and only allow calling time.Now when the ticker fires.
//
// Returned value may have +-100ms error.
func DefaultTimeNow() time.Time {
	if shouldCallTimeNow.Load() {
		lastTimeNow = time.Now()
		shouldCallTimeNow.Store(false)
	}
	return lastTimeNow
}

func init() {
	go func() {
		for {
			select {
			case <-task.RootContext().Done():
				return
			case <-timeNowTicker.C:
				shouldCallTimeNow.Store(true)
			}
		}
	}()
}