package clock

import (
	
	
	
	
)

func ( *Mock) ( context.Context,  time.Duration) (context.Context, context.CancelFunc) {
	return .WithDeadline(, .Now().Add())
}

func ( *Mock) ( context.Context,  time.Time) (context.Context, context.CancelFunc) {
	if ,  := .Deadline();  && .Before() {
		// The current deadline is already sooner than the new one.
		return context.WithCancel()
	}
	 := &timerCtx{clock: , parent: , deadline: , done: make(chan struct{})}
	propagateCancel(, )
	 := .Until()
	if  <= 0 {
		.cancel(context.DeadlineExceeded) // deadline has already passed
		return , func() {}
	}
	.Lock()
	defer .Unlock()
	if .err == nil {
		.timer = .AfterFunc(, func() {
			.cancel(context.DeadlineExceeded)
		})
	}
	return , func() { .cancel(context.Canceled) }
}

// propagateCancel arranges for child to be canceled when parent is.
func propagateCancel( context.Context,  *timerCtx) {
	if .Done() == nil {
		return // parent is never canceled
	}
	go func() {
		select {
		case <-.Done():
			.cancel(.Err())
		case <-.Done():
		}
	}()
}

type timerCtx struct {
	sync.Mutex

	clock    Clock
	parent   context.Context
	deadline time.Time
	done     chan struct{}

	err   error
	timer *Timer
}

func ( *timerCtx) ( error) {
	.Lock()
	defer .Unlock()
	if .err != nil {
		return // already canceled
	}
	.err = 
	close(.done)
	if .timer != nil {
		.timer.Stop()
		.timer = nil
	}
}

func ( *timerCtx) () ( time.Time,  bool) { return .deadline, true }

func ( *timerCtx) () <-chan struct{} { return .done }

func ( *timerCtx) () error { return .err }

func ( *timerCtx) ( interface{}) interface{} { return .parent.Value() }

func ( *timerCtx) () string {
	return fmt.Sprintf("clock.WithDeadline(%s [%s])", .deadline, .deadline.Sub(.clock.Now()))
}