// Code generated by gtrace. DO NOT EDIT.

package gtrace

import (
	"context"
	"time"

	"github.com/ydb-platform/ydb-go-sdk/v3/trace"
)

// retryComposeOptions is a holder of options
type retryComposeOptions struct {
	panicCallback func(e interface{})
}

// RetryOption specified Retry compose option
// Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals
type RetryComposeOption func(o *retryComposeOptions)

// WithRetryPanicCallback specified behavior on panic
// Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals
func WithRetryPanicCallback(cb func(e interface{})) RetryComposeOption {
	return func(o *retryComposeOptions) {
		o.panicCallback = cb
	}
}

// Compose returns a new Retry which has functional fields composed both from lhs and rhs.
// Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals
func Compose(lhs *trace.Retry, rhs *trace.Retry, opts ...RetryComposeOption) *trace.Retry {
	if lhs == nil {
		return rhs
	}
	var ret trace.Retry
	options := retryComposeOptions{}
	for _, opt := range opts {
		if opt != nil {
			opt(&options)
		}
	}
	{
		h1 := lhs.OnRetry
		h2 := rhs.OnRetry
		ret.OnRetry = func(r trace.RetryLoopStartInfo) func(trace.RetryLoopDoneInfo) {
			if options.panicCallback != nil {
				defer func() {
					if e := recover(); e != nil {
						options.panicCallback(e)
					}
				}()
			}
			var r1, r2 func(trace.RetryLoopDoneInfo)
			if h1 != nil {
				r1 = h1(r)
			}
			if h2 != nil {
				r2 = h2(r)
			}
			return func(r trace.RetryLoopDoneInfo) {
				if options.panicCallback != nil {
					defer func() {
						if e := recover(); e != nil {
							options.panicCallback(e)
						}
					}()
				}
				if r1 != nil {
					r1(r)
				}
				if r2 != nil {
					r2(r)
				}
			}
		}
	}
	{
		h1 := lhs.OnRetryAttempt
		h2 := rhs.OnRetryAttempt
		ret.OnRetryAttempt = func(r trace.RetryAttemptStartInfo) func(trace.RetryAttemptDoneInfo) {
			if options.panicCallback != nil {
				defer func() {
					if e := recover(); e != nil {
						options.panicCallback(e)
					}
				}()
			}
			var r1, r2 func(trace.RetryAttemptDoneInfo)
			if h1 != nil {
				r1 = h1(r)
			}
			if h2 != nil {
				r2 = h2(r)
			}
			return func(r trace.RetryAttemptDoneInfo) {
				if options.panicCallback != nil {
					defer func() {
						if e := recover(); e != nil {
							options.panicCallback(e)
						}
					}()
				}
				if r1 != nil {
					r1(r)
				}
				if r2 != nil {
					r2(r)
				}
			}
		}
	}
	return &ret
}
func onRetry(t *trace.Retry, r trace.RetryLoopStartInfo) func(trace.RetryLoopDoneInfo) {
	fn := t.OnRetry
	if fn == nil {
		return func(trace.RetryLoopDoneInfo) {
			return
		}
	}
	res := fn(r)
	if res == nil {
		return func(trace.RetryLoopDoneInfo) {
			return
		}
	}
	return res
}
func onRetryAttempt(t *trace.Retry, r trace.RetryAttemptStartInfo) func(trace.RetryAttemptDoneInfo) {
	fn := t.OnRetryAttempt
	if fn == nil {
		return func(trace.RetryAttemptDoneInfo) {
			return
		}
	}
	res := fn(r)
	if res == nil {
		return func(trace.RetryAttemptDoneInfo) {
			return
		}
	}
	return res
}
// Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals
func RetryOnRetry(t *trace.Retry, c *context.Context, c1 trace.Call, label string, idempotent bool, nestedCall bool) func(attempts int, _ error) {
	var p trace.RetryLoopStartInfo
	p.Context = c
	p.Call = c1
	p.Label = label
	p.Idempotent = idempotent
	p.NestedCall = nestedCall
	res := onRetry(t, p)
	return func(attempts int, e error) {
		var p trace.RetryLoopDoneInfo
		p.Attempts = attempts
		p.Error = e
		res(p)
	}
}
// Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals
func RetryOnRetryAttempt(t *trace.Retry, c *context.Context, c1 trace.Call, label string, idempotent bool, attempt int, backoff time.Duration) func(error) {
	var p trace.RetryAttemptStartInfo
	p.Context = c
	p.Call = c1
	p.Label = label
	p.Idempotent = idempotent
	p.Attempt = attempt
	p.Backoff = backoff
	res := onRetryAttempt(t, p)
	return func(e error) {
		var p trace.RetryAttemptDoneInfo
		p.Error = e
		res(p)
	}
}
