// SPDX-License-Identifier: Apache-2.0

package solver

import (
	"smariot.com/tsp/internal/solver/bounded"
	"smariot.com/tsp/internal/solver/bounded_tracking"
	"smariot.com/tsp/internal/solver/problem"
	"smariot.com/tsp/internal/solver/unbounded"
	"smariot.com/tsp/internal/solver/unbounded_tracking"
)

type Solver[State comparable] interface {
	Push(State)
	Pop() (State, bool)
	Reset()
}

// New creates a new state solver for the given problem and capacity.
//
// A capacity of 0 implies no limit, and we won't maintain a max heap.
//
// If P implements ProblemStateUpdates, then the solver will keep track of known states.
func New[P problem.Problem[State], State comparable](p P, capacity int) Solver[State] {
	switch {
	case capacity == 0 && problem.RequiresStateUpdates[P](p):
		return bounded_tracking.New(p)
	case capacity == 0:
		return bounded.New(p)
	case problem.RequiresStateUpdates[P](p):
		return unbounded_tracking.New(p, capacity)
	default:
		return unbounded.New(p, capacity)
	}
}