package clock

import (
	
	
	
	
)

// Re-export of time.Duration
type Duration = time.Duration

// Clock represents an interface to the functions in the standard library time
// package. Two implementations are available in the clock package. The first
// is a real-time clock which simply wraps the time package's functions. The
// second is a mock clock which will only change when
// programmatically adjusted.
type Clock interface {
	After(d time.Duration) <-chan time.Time
	AfterFunc(d time.Duration, f func()) *Timer
	Now() time.Time
	Since(t time.Time) time.Duration
	Until(t time.Time) time.Duration
	Sleep(d time.Duration)
	Tick(d time.Duration) <-chan time.Time
	Ticker(d time.Duration) *Ticker
	Timer(d time.Duration) *Timer
	WithDeadline(parent context.Context, d time.Time) (context.Context, context.CancelFunc)
	WithTimeout(parent context.Context, t time.Duration) (context.Context, context.CancelFunc)
}

// New returns an instance of a real-time clock.
func () Clock {
	return &clock{}
}

// clock implements a real-time clock by simply wrapping the time package functions.
type clock struct{}

func ( *clock) ( time.Duration) <-chan time.Time { return time.After() }

func ( *clock) ( time.Duration,  func()) *Timer {
	return &Timer{timer: time.AfterFunc(, )}
}

func ( *clock) () time.Time { return time.Now() }

func ( *clock) ( time.Time) time.Duration { return time.Since() }

func ( *clock) ( time.Time) time.Duration { return time.Until() }

func ( *clock) ( time.Duration) { time.Sleep() }

func ( *clock) ( time.Duration) <-chan time.Time { return time.Tick() }

func ( *clock) ( time.Duration) *Ticker {
	 := time.NewTicker()
	return &Ticker{C: .C, ticker: }
}

func ( *clock) ( time.Duration) *Timer {
	 := time.NewTimer()
	return &Timer{C: .C, timer: }
}

func ( *clock) ( context.Context,  time.Time) (context.Context, context.CancelFunc) {
	return context.WithDeadline(, )
}

func ( *clock) ( context.Context,  time.Duration) (context.Context, context.CancelFunc) {
	return context.WithTimeout(, )
}

// Mock represents a mock clock that only moves forward programmically.
// It can be preferable to a real-time clock when testing time-based functionality.
type Mock struct {
	// mu protects all other fields in this struct, and the data that they
	// point to.
	mu sync.Mutex

	now    time.Time   // current time
	timers clockTimers // tickers & timers
}

// NewMock returns an instance of a mock clock.
// The current time of the mock clock on initialization is the Unix epoch.
func () *Mock {
	return &Mock{now: time.Unix(0, 0)}
}

// Add moves the current time of the mock clock forward by the specified duration.
// This should only be called from a single goroutine at a time.
func ( *Mock) ( time.Duration) {
	// Calculate the final current time.
	.mu.Lock()
	 := .now.Add()
	.mu.Unlock()

	// Continue to execute timers until there are no more before the new time.
	for {
		if !.runNextTimer() {
			break
		}
	}

	// Ensure that we end with the new time.
	.mu.Lock()
	.now = 
	.mu.Unlock()

	// Give a small buffer to make sure that other goroutines get handled.
	gosched()
}

// Set sets the current time of the mock clock to a specific one.
// This should only be called from a single goroutine at a time.
func ( *Mock) ( time.Time) {
	// Continue to execute timers until there are no more before the new time.
	for {
		if !.runNextTimer() {
			break
		}
	}

	// Ensure that we end with the new time.
	.mu.Lock()
	.now = 
	.mu.Unlock()

	// Give a small buffer to make sure that other goroutines get handled.
	gosched()
}

// WaitForAllTimers sets the clock until all timers are expired
func ( *Mock) () time.Time {
	// Continue to execute timers until there are no more
	for {
		.mu.Lock()
		if len(.timers) == 0 {
			.mu.Unlock()
			return .Now()
		}

		sort.Sort(.timers)
		 := .timers[len(.timers)-1].Next()
		.mu.Unlock()
		.Set()
	}
}

// runNextTimer executes the next timer in chronological order and moves the
// current time to the timer's next tick time. The next time is not executed if
// its next time is after the max time. Returns true if a timer was executed.
func ( *Mock) ( time.Time) bool {
	.mu.Lock()

	// Sort timers by time.
	sort.Sort(.timers)

	// If we have no more timers then exit.
	if len(.timers) == 0 {
		.mu.Unlock()
		return false
	}

	// Retrieve next timer. Exit if next tick is after new time.
	 := .timers[0]
	if .Next().After() {
		.mu.Unlock()
		return false
	}

	// Move "now" forward and unlock clock.
	.now = .Next()
	 := .now
	.mu.Unlock()

	// Execute timer.
	.Tick()
	return true
}

// After waits for the duration to elapse and then sends the current time on the returned channel.
func ( *Mock) ( time.Duration) <-chan time.Time {
	return .Timer().C
}

// AfterFunc waits for the duration to elapse and then executes a function in its own goroutine.
// A Timer is returned that can be stopped.
func ( *Mock) ( time.Duration,  func()) *Timer {
	.mu.Lock()
	defer .mu.Unlock()
	 := make(chan time.Time, 1)
	 := &Timer{
		c:       ,
		fn:      ,
		mock:    ,
		next:    .now.Add(),
		stopped: false,
	}
	.timers = append(.timers, (*internalTimer)())
	return 
}

// Now returns the current wall time on the mock clock.
func ( *Mock) () time.Time {
	.mu.Lock()
	defer .mu.Unlock()
	return .now
}

// Since returns time since `t` using the mock clock's wall time.
func ( *Mock) ( time.Time) time.Duration {
	return .Now().Sub()
}

// Until returns time until `t` using the mock clock's wall time.
func ( *Mock) ( time.Time) time.Duration {
	return .Sub(.Now())
}

// Sleep pauses the goroutine for the given duration on the mock clock.
// The clock must be moved forward in a separate goroutine.
func ( *Mock) ( time.Duration) {
	<-.After()
}

// Tick is a convenience function for Ticker().
// It will return a ticker channel that cannot be stopped.
func ( *Mock) ( time.Duration) <-chan time.Time {
	return .Ticker().C
}

// Ticker creates a new instance of Ticker.
func ( *Mock) ( time.Duration) *Ticker {
	.mu.Lock()
	defer .mu.Unlock()
	 := make(chan time.Time, 1)
	 := &Ticker{
		C:    ,
		c:    ,
		mock: ,
		d:    ,
		next: .now.Add(),
	}
	.timers = append(.timers, (*internalTicker)())
	return 
}

// Timer creates a new instance of Timer.
func ( *Mock) ( time.Duration) *Timer {
	.mu.Lock()
	 := make(chan time.Time, 1)
	 := &Timer{
		C:       ,
		c:       ,
		mock:    ,
		next:    .now.Add(),
		stopped: false,
	}
	.timers = append(.timers, (*internalTimer)())
	 := .now
	.mu.Unlock()
	.runNextTimer()
	return 
}

// removeClockTimer removes a timer from m.timers. m.mu MUST be held
// when this method is called.
func ( *Mock) ( clockTimer) {
	for ,  := range .timers {
		if  ==  {
			copy(.timers[:], .timers[+1:])
			.timers[len(.timers)-1] = nil
			.timers = .timers[:len(.timers)-1]
			break
		}
	}
	sort.Sort(.timers)
}

// clockTimer represents an object with an associated start time.
type clockTimer interface {
	Next() time.Time
	Tick(time.Time)
}

// clockTimers represents a list of sortable timers.
type clockTimers []clockTimer

func ( clockTimers) () int           { return len() }
func ( clockTimers) (,  int)      { [], [] = [], [] }
func ( clockTimers) (,  int) bool { return [].Next().Before([].Next()) }

// Timer represents a single event.
// The current time will be sent on C, unless the timer was created by AfterFunc.
type Timer struct {
	C       <-chan time.Time
	c       chan time.Time
	timer   *time.Timer // realtime impl, if set
	next    time.Time   // next tick time
	mock    *Mock       // mock clock, if set
	fn      func()      // AfterFunc function, if set
	stopped bool        // True if stopped, false if running
}

// Stop turns off the ticker.
func ( *Timer) () bool {
	if .timer != nil {
		return .timer.Stop()
	}

	.mock.mu.Lock()
	 := !.stopped
	.mock.removeClockTimer((*internalTimer)())
	.stopped = true
	.mock.mu.Unlock()
	return 
}

// Reset changes the expiry time of the timer
func ( *Timer) ( time.Duration) bool {
	if .timer != nil {
		return .timer.Reset()
	}

	.mock.mu.Lock()
	.next = .mock.now.Add()
	defer .mock.mu.Unlock()

	 := !.stopped
	if .stopped {
		.mock.timers = append(.mock.timers, (*internalTimer)())
	}

	.stopped = false
	return 
}

type internalTimer Timer

func ( *internalTimer) () time.Time { return .next }
func ( *internalTimer) ( time.Time) {
	// a gosched() after ticking, to allow any consequences of the
	// tick to complete
	defer gosched()

	.mock.mu.Lock()
	if .fn != nil {
		// defer function execution until the lock is released, and
		defer func() { go .fn() }()
	} else {
		.c <- 
	}
	.mock.removeClockTimer((*internalTimer)())
	.stopped = true
	.mock.mu.Unlock()
}

// Ticker holds a channel that receives "ticks" at regular intervals.
type Ticker struct {
	C       <-chan time.Time
	c       chan time.Time
	ticker  *time.Ticker  // realtime impl, if set
	next    time.Time     // next tick time
	mock    *Mock         // mock clock, if set
	d       time.Duration // time between ticks
	stopped bool          // True if stopped, false if running
}

// Stop turns off the ticker.
func ( *Ticker) () {
	if .ticker != nil {
		.ticker.Stop()
	} else {
		.mock.mu.Lock()
		.mock.removeClockTimer((*internalTicker)())
		.stopped = true
		.mock.mu.Unlock()
	}
}

// Reset resets the ticker to a new duration.
func ( *Ticker) ( time.Duration) {
	if .ticker != nil {
		.ticker.Reset()
		return
	}

	.mock.mu.Lock()
	defer .mock.mu.Unlock()

	if .stopped {
		.mock.timers = append(.mock.timers, (*internalTicker)())
		.stopped = false
	}

	.d = 
	.next = .mock.now.Add()
}

type internalTicker Ticker

func ( *internalTicker) () time.Time { return .next }
func ( *internalTicker) ( time.Time) {
	select {
	case .c <- :
	default:
	}
	.mock.mu.Lock()
	.next = .Add(.d)
	.mock.mu.Unlock()
	gosched()
}

// Sleep momentarily so that other goroutines can process.
func gosched() { time.Sleep(1 * time.Millisecond) }

var (
	// type checking
	_ Clock = &Mock{}
)