package throttling

import (
	"context"
	"time"
)

func (suite *ThrottlerTestSuite) Test_AsyncDeliverOneValue() {
	value := 0

	pollInterval := 10 * time.Millisecond

	ctx, cancel := context.WithCancel(context.Background())
	throttler := NewAsyncThrottler[int](ctx, func(v *int) {
		value = *v
	}, time.Second, pollInterval)
	defer cancel()

	t0 := time.Now()
	v := 1
	currentTime.now = t0
	throttler.Notify(&v)
	time.Sleep(2 * pollInterval)
	suite.Equal(v, value)

	// subsequent ping will not lead to a notification
	value = 0
	time.Sleep(2 * pollInterval)
	suite.Equal(0, value)
}

func (suite *ThrottlerTestSuite) Test_AsyncTwoNotificationsInSHortSucessionSecondOneIsDeliverdWithDelay() {
	value := 0
	delayMs := 1000

	pollInterval := 10 * time.Millisecond

	ctx, cancel := context.WithCancel(context.Background())
	throttler := NewAsyncThrottler[int](ctx, func(v *int) {
		value = *v
	}, time.Second, pollInterval)
	defer cancel()

	t0 := time.Now()
	v1 := 1
	// v2 will not be delivered, the last value in the time interval will be
	v2 := 2
	v3 := 3
	currentTime.now = t0
	throttler.Notify(&v1)
	time.Sleep(2 * pollInterval)
	suite.Equal(v1, value)

	throttler.Notify(&v2)
	throttler.Notify(&v3)
	time.Sleep(2 * pollInterval)
	suite.Equal(v1, value)

	currentTime.now = t0.Add(time.Duration(delayMs-1) * time.Millisecond)
	time.Sleep(2 * pollInterval)
	suite.Equal(v1, value)

	currentTime.now = t0.Add(time.Duration(delayMs) * time.Millisecond)
	time.Sleep(2 * pollInterval)
	suite.Equal(v3, value)

	// another ping won't deliver the same value again.
	value = 0
	currentTime.now = t0.Add(time.Duration(delayMs) * time.Millisecond)
	time.Sleep(2 * pollInterval)
	suite.Equal(0, value)
}