package backoff

import (
	
	
	
)

// Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff.
//
// Ticks will continue to arrive when the previous operation is still running,
// so operations that take a while to fail could run in quick succession.
type Ticker struct {
	C        <-chan time.Time
	c        chan time.Time
	b        BackOff
	ctx      context.Context
	timer    Timer
	stop     chan struct{}
	stopOnce sync.Once
}

// NewTicker returns a new Ticker containing a channel that will send
// the time at times specified by the BackOff argument. Ticker is
// guaranteed to tick at least once.  The channel is closed when Stop
// method is called or BackOff stops. It is not safe to manipulate the
// provided backoff policy (notably calling NextBackOff or Reset)
// while the ticker is running.
func ( BackOff) *Ticker {
	return NewTickerWithTimer(, &defaultTimer{})
}

// NewTickerWithTimer returns a new Ticker with a custom timer.
// A default timer that uses system timer is used when nil is passed.
func ( BackOff,  Timer) *Ticker {
	if  == nil {
		 = &defaultTimer{}
	}
	 := make(chan time.Time)
	 := &Ticker{
		C:     ,
		c:     ,
		b:     ,
		ctx:   getContext(),
		timer: ,
		stop:  make(chan struct{}),
	}
	.b.Reset()
	go .run()
	return 
}

// Stop turns off a ticker. After Stop, no more ticks will be sent.
func ( *Ticker) () {
	.stopOnce.Do(func() { close(.stop) })
}

func ( *Ticker) () {
	 := .c
	defer close()

	// Ticker is guaranteed to tick at least once.
	 := .send(time.Now())

	for {
		if  == nil {
			return
		}

		select {
		case  := <-:
			 = .send()
		case <-.stop:
			.c = nil // Prevent future ticks from being sent to the channel.
			return
		case <-.ctx.Done():
			return
		}
	}
}

func ( *Ticker) ( time.Time) <-chan time.Time {
	select {
	case .c <- :
	case <-.stop:
		return nil
	}

	 := .b.NextBackOff()
	if  == Stop {
		.Stop()
		return nil
	}

	.timer.Start()
	return .timer.C()
}