package limits

import (
	
	
	
	
	
	
)

const (
	// MaxOptimizationWorkUnits bounds one hierarchy or placement optimization.
	MaxOptimizationWorkUnits uint64 = 250_000_000

	optimizationContextCheckStride uint64 = 64
)

// ErrOptimizationResourceLimit reports exhausted or overflowing optimization
// work accounting.
var ErrOptimizationResourceLimit = errors.New("TALA optimization resource limit exceeded")

// OptimizationWorkGuard accounts one complete hierarchy or placement
// optimization. The limit is an explicit ceiling; zero permits cancellation
// checks but no charged work.
type OptimizationWorkGuard struct {
	ctx      context.Context
	location string
	used     uint64
	limit    uint64
}

// NewOptimizationWorkGuard constructs a guard and observes cancellation before
// any optimization work begins.
func ( context.Context,  string,  uint64) (*OptimizationWorkGuard, error) {
	if  == nil {
		return nil, fmt.Errorf("TALA %s requires a context", )
	}
	 := &OptimizationWorkGuard{ctx: , location: , limit: }
	if  := .Finish();  != nil {
		return nil, 
	}
	return , nil
}

// Step charges one optimization work unit.
func ( *OptimizationWorkGuard) () error {
	return .Add(1)
}

// Add charges amount optimization work units.
func ( *OptimizationWorkGuard) ( uint64) error {
	if  == 0 {
		return .Check()
	}
	if math.MaxUint64-.used <  {
		return fmt.Errorf("%w: %s work arithmetic overflow", ErrOptimizationResourceLimit, .location)
	}
	 := .used
	 :=  + 
	if  > .limit {
		return fmt.Errorf("%w: TALA %s work exceeds limit %d", ErrOptimizationResourceLimit, .location, .limit)
	}
	.used = 
	if /optimizationContextCheckStride != /optimizationContextCheckStride {
		return .Check()
	}
	return nil
}

// AddProduct multiplies two work dimensions without allowing arithmetic
// overflow.
func ( *OptimizationWorkGuard) (,  uint64) error {
	if  != 0 &&  > math.MaxUint64/ {
		return fmt.Errorf("%w: %s work arithmetic overflow", ErrOptimizationResourceLimit, .location)
	}
	return .Add( * )
}

// AddSort charges the comparison bound for sorting length values.
func ( *OptimizationWorkGuard) ( int) error {
	if  <= 1 {
		return .Check()
	}
	return .AddProduct(uint64(), uint64(bits.Len64(uint64(-1))))
}

// Check observes optimization cancellation immediately.
func ( *OptimizationWorkGuard) () error {
	if  := .ctx.Err();  != nil {
		return fmt.Errorf("%s: %w", .location, )
	}
	return nil
}

// Finish observes cancellation at an optimization boundary.
func ( *OptimizationWorkGuard) () error {
	return .Check()
}

// Location returns the operation name used in diagnostics.
func ( *OptimizationWorkGuard) () string {
	return .location
}

// Used returns the accepted work units.
func ( *OptimizationWorkGuard) () uint64 {
	return .used
}

// Shuffle is math/rand.Shuffle's Fisher-Yates implementation with a guard
// check before every random draw. Its reduction algorithm and draw order are
// intentionally identical so seeded layout output remains stable.
func [ any]( [],  *rand.Rand,  *OptimizationWorkGuard) error {
	if  == nil {
		return fmt.Errorf("TALA %s shuffle requires a random generator", .location)
	}
	 := len() - 1
	for ;  > 1<<31-1-1; -- {
		if  := .Step();  != nil {
			return 
		}
		 := int(.Int63n(int64( + 1)))
		[], [] = [], []
	}
	for ;  > 0; -- {
		,  := shuffleIndex(, int32(+1), )
		if  != nil {
			return 
		}
		[], [] = [], []
	}
	return nil
}

func shuffleIndex( *rand.Rand,  int32,  *OptimizationWorkGuard) (int32, error) {
	if  := .Step();  != nil {
		return 0, 
	}
	 := .Uint32()
	 := uint64() * uint64()
	 := uint32()
	if  < uint32() {
		 := uint32(-) % uint32()
		for  <  {
			if  := .Step();  != nil {
				return 0, 
			}
			 = .Uint32()
			 = uint64() * uint64()
			 = uint32()
		}
	}
	return int32( >> 32), nil
}