// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT

package sctp

import (
	
	
	
)

const (
	ackInterval time.Duration = 200 * time.Millisecond
)

// ackTimerObserver is the inteface to an ack timer observer.
type ackTimerObserver interface {
	onAckTimeout()
}

type ackTimerState uint8

const (
	ackTimerStopped ackTimerState = iota
	ackTimerStarted
	ackTimerClosed
)

// ackTimer provides the retnransmission timer conforms with RFC 4960 Sec 6.3.1.
type ackTimer struct {
	timer    *time.Timer
	observer ackTimerObserver
	mutex    sync.Mutex
	state    ackTimerState
	pending  uint8
}

// newAckTimer creates a new acknowledgement timer used to enable delayed ack.
func newAckTimer( ackTimerObserver) *ackTimer {
	 := &ackTimer{observer: }
	.timer = time.AfterFunc(math.MaxInt64, .timeout)
	.timer.Stop()

	return 
}

func ( *ackTimer) () {
	.mutex.Lock()
	if .pending--; .pending == 0 && .state == ackTimerStarted {
		.state = ackTimerStopped
		defer .observer.onAckTimeout()
	}
	.mutex.Unlock()
}

// start starts the timer.
func ( *ackTimer) () bool {
	.mutex.Lock()
	defer .mutex.Unlock()

	// this timer is already closed or already running
	if .state != ackTimerStopped {
		return false
	}

	.state = ackTimerStarted
	.pending++
	.timer.Reset(ackInterval)

	return true
}

// stops the timer. this is similar to stop() but subsequent start() call
// will fail (the timer is no longer usable).
func ( *ackTimer) () {
	.mutex.Lock()
	defer .mutex.Unlock()

	if .state == ackTimerStarted {
		if .timer.Stop() {
			.pending--
		}
		.state = ackTimerStopped
	}
}

// closes the timer. this is similar to stop() but subsequent start() call
// will fail (the timer is no longer usable).
func ( *ackTimer) () {
	.mutex.Lock()
	defer .mutex.Unlock()

	if .state == ackTimerStarted && .timer.Stop() {
		.pending--
	}
	.state = ackTimerClosed
}

// isRunning tests if the timer is running.
// Debug purpose only.
func ( *ackTimer) () bool {
	.mutex.Lock()
	defer .mutex.Unlock()

	return .state == ackTimerStarted
}