package hu.webarticum.jsatbuilder.builder.core;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import hu.webarticum.jsatbuilder.builder.core.Constraint;
import hu.webarticum.jsatbuilder.builder.core.Definition;
import hu.webarticum.jsatbuilder.builder.core.Dependant;
import hu.webarticum.jsatbuilder.builder.core.SolverFiller;
import hu.webarticum.jsatbuilder.solver.core.Solver;

public class ConstraintSetSolverFiller implements SolverFiller {
    
    private final boolean linked;
    
    private List<Constraint> constraints = new ArrayList<Constraint>();
    
    public ConstraintSetSolverFiller() {
        this(false);
    }
    
    public ConstraintSetSolverFiller(boolean linked) {
        this.linked = linked;
    }
    
    public void add(Constraint constraint) {
        constraints.add(constraint);
    }
    
    @Override
    public void fillSolver(Solver solver) {
        Set<Dependant> handledDependants = createDependantSet();
        Set<Dependant> unhandledDependants = createDependantSet();
        
        for (Constraint constraint: constraints) {
            if (!constraint.isRemoved()) {
                unhandledDependants.add(constraint);
            }
        }
        
        while (!unhandledDependants.isEmpty()) {
            Set<Dependant> newDependants = createDependantSet();
            
            for (Dependant dependant: unhandledDependants) {
                for (Definition definition: dependant.getDependencies()) {
                    if (
                        definition instanceof Dependant &&
                        !handledDependants.contains(definition) &&
                        !unhandledDependants.contains(definition)
                    ) {
                        newDependants.add(dependant);
                    }
                }
            }
            
            handledDependants.addAll(unhandledDependants);
            
            unhandledDependants = newDependants;
        }
        
        for (Dependant dependant: handledDependants) {
            if (dependant instanceof SolverFiller) {
                ((SolverFiller)dependant).fillSolver(solver);
            }
        }
    }
    
    private Set<Dependant> createDependantSet() {
        return linked ? new LinkedHashSet<Dependant>() : new HashSet<Dependant>();
    }

}

@@ -1834,17 +1834,18 @@
 nts.add(
-d
+(D
 ependant
@@ -1845,16 +1845,27 @@
 pendant)
+definition)
 ;%0A      

Fix dependant collector in ConstraintSetSolverFiller