package policy

import (
	
	
	

	
	
)

// BaseFailurePolicy provides a base for implementing FailurePolicyBuilder.
type BaseFailurePolicy[ any] struct {
	// Indicates whether errors are checked by a configured failure condition
	errorsChecked bool
	// Conditions that determine whether an execution is a failure
	failureConditions []func(result , err error) bool
	onSuccess         func(failsafe.ExecutionEvent[])
	onFailure         func(failsafe.ExecutionEvent[])
}

func ( *BaseFailurePolicy[]) ( ...error) {
	for ,  := range  {
		 := 
		.failureConditions = append(.failureConditions, func( ,  error) bool {
			return errors.Is(, )
		})
	}
	.errorsChecked = true
}

func ( *BaseFailurePolicy[]) ( ...any) {
	for ,  := range  {
		 := 
		.failureConditions = append(.failureConditions, func( ,  error) bool {
			return util.ErrorTypesMatch(, )
		})
	}
	.errorsChecked = true
}

func ( *BaseFailurePolicy[]) ( ) {
	.failureConditions = append(.failureConditions, func( ,  error) bool {
		return reflect.DeepEqual(, )
	})
}

func ( *BaseFailurePolicy[]) ( func(, error) bool) {
	.failureConditions = append(.failureConditions, )
	.errorsChecked = true
}

func ( *BaseFailurePolicy[]) ( func( failsafe.ExecutionEvent[])) {
	.onSuccess = 
}

func ( *BaseFailurePolicy[]) ( func( failsafe.ExecutionEvent[])) {
	.onFailure = 
}

func ( *BaseFailurePolicy[]) ( ,  error) bool {
	if len(.failureConditions) == 0 {
		return  != nil
	}
	if util.AppliesToAny(.failureConditions, , ) {
		return true
	}

	// Fail by default if an error exists and was not checked by a condition
	return  != nil && !.errorsChecked
}

// BaseDelayablePolicy provides a base for implementing DelayablePolicyBuilder.
type BaseDelayablePolicy[ any] struct {
	Delay     time.Duration
	DelayFunc failsafe.DelayFunc[]
}

func ( *BaseDelayablePolicy[]) ( time.Duration) {
	.Delay = 
}

func ( *BaseDelayablePolicy[]) ( failsafe.DelayFunc[]) {
	.DelayFunc = 
}

// ComputeDelay returns a computed delay else -1 if no delay could be computed.
func ( *BaseDelayablePolicy[]) ( failsafe.ExecutionAttempt[]) time.Duration {
	if  != nil && .DelayFunc != nil {
		return .DelayFunc()
	}
	return -1
}

// BaseAbortablePolicy provides a base for implementing policies that can be aborted or canceled.
type BaseAbortablePolicy[ any] struct {
	// Conditions that determine whether the policy should be aborted
	abortConditions []func(result , err error) bool
}

func ( *BaseAbortablePolicy[]) ( ) {
	.abortConditions = append(.abortConditions, func( ,  error) bool {
		return reflect.DeepEqual(, )
	})
}

func ( *BaseAbortablePolicy[]) ( ...error) {
	for ,  := range  {
		 := 
		.abortConditions = append(.abortConditions, func( ,  error) bool {
			return errors.Is(, )
		})
	}
}

func ( *BaseAbortablePolicy[]) ( ...any) {
	for ,  := range  {
		 := 
		.abortConditions = append(.abortConditions, func( ,  error) bool {
			return util.ErrorTypesMatch(, )
		})
	}
}

func ( *BaseAbortablePolicy[]) ( func(, error) bool) {
	.abortConditions = append(.abortConditions, func( ,  error) bool {
		return (, )
	})
}

func ( *BaseAbortablePolicy[]) () bool {
	return len(.abortConditions) > 0
}

func ( *BaseAbortablePolicy[]) ( ,  error) bool {
	return util.AppliesToAny(.abortConditions, , )
}