package pond

import (
	

	
)

// ResultPool is a pool that can be used to submit tasks that return a result.
type ResultPool[ any] interface {
	BasePool

	// Submits a task to the pool and returns a future that can be used to wait for the task to complete and get the result.
	// The pool will not accept new tasks after it has been stopped.
	// If the pool has been stopped, this method will return ErrPoolStopped.
	Submit(task func() ) ResultTask[]

	// Submits a task to the pool and returns a future that can be used to wait for the task to complete and get the result.
	// The task function must return a result and an error.
	// The pool will not accept new tasks after it has been stopped.
	// If the pool has been stopped, this method will return ErrPoolStopped.
	SubmitErr(task func() (, error)) ResultTask[]

	// Attempts to submit a task to the pool and returns a future that can be used to wait for the task to complete
	// and a boolean indicating whether the task was submitted successfully.
	// The pool will not accept new tasks after it has been stopped.
	// If the pool has been stopped, this method will return ErrPoolStopped.
	TrySubmit(task func() ) (ResultTask[], bool)

	// Attempts to submit a task to the pool and returns a future that can be used to wait for the task to complete
	// and a boolean indicating whether the task was submitted successfully.
	// The task function must return a result and an error.
	// The pool will not accept new tasks after it has been stopped.
	// If the pool has been stopped, this method will return ErrPoolStopped.
	TrySubmitErr(task func() (, error)) (ResultTask[], bool)

	// Creates a new subpool with the specified maximum concurrency and options.
	NewSubpool(maxConcurrency int, options ...Option) ResultPool[]

	// Creates a new task group.
	NewGroup() ResultTaskGroup[]

	// Creates a new task group with the specified context.
	NewGroupContext(ctx context.Context) ResultTaskGroup[]
}

type resultPool[ any] struct {
	*pool
}

func ( *resultPool[]) () ResultTaskGroup[] {
	return newResultTaskGroup[](.pool, .Context())
}

func ( *resultPool[]) ( context.Context) ResultTaskGroup[] {
	return newResultTaskGroup[](.pool, )
}

func ( *resultPool[]) ( func() ) ResultTask[] {
	,  := .submit(, .nonBlocking)
	return 
}

func ( *resultPool[]) ( func() (, error)) ResultTask[] {
	,  := .submit(, .nonBlocking)
	return 
}

func ( *resultPool[]) ( func() ) (ResultTask[], bool) {
	return .submit(, true)
}

func ( *resultPool[]) ( func() (, error)) (ResultTask[], bool) {
	return .submit(, true)
}

func ( *resultPool[]) ( any,  bool) (ResultTask[], bool) {
	 := .Context()
	,  := future.NewValueFuture[]()

	if .Stopped() {
		var  
		(, ErrPoolStopped)
		return , false
	}

	 := wrapTask[, func(, error)](, , , .pool.panicRecovery)

	if  := .pool.submit(, );  != nil {
		var  
		(, )
		return , false
	}

	return , true
}

func ( *resultPool[]) ( int,  ...Option) ResultPool[] {
	return newResultPool[](, .pool, ...)
}

func newResultPool[ any]( int,  *pool,  ...Option) *resultPool[] {
	return &resultPool[]{
		pool: newPool(, , ...),
	}
}

// NewResultPool creates a new result pool with the given maximum concurrency and options.
// Result pools are generic pools that can be used to submit tasks that return a result.
// The new maximum concurrency must be greater than or equal to 0 (0 means no limit).
func [ any]( int,  ...Option) ResultPool[] {
	return newResultPool[](, nil, ...)
}