package sudoku.solver;

import java.util.List;
import java.util.Random;
import java.util.concurrent.CancellationException;

import sudoku.structure.Cell;
import sudoku.structure.MultiDoku;

public class MixedSolver implements Solver {

    /**
     * Résout le MultiDoku passé en paramètre, avec règles de déduction et
     * backtracking.
     *
     * @param doku MultiDoku, MultiDoku à résoudre.
     * @return boolean, valant true si le MultiDoku est résolu, false sinon.
     */
    @Override
    public boolean solve(MultiDoku doku, List<SolverStep> steps) {
        Random rand = new Random();

        if (Thread.interrupted()) {
            throw new CancellationException("User wants to stop the solver");
        }

        if (doku.isSolved()) {
            return true;
        }

        Cell cellToFill = doku.getFirstEmptyCell();
        if (cellToFill == null) {
            return false;
        }

        List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();

        if (possibleSymbols.size() == 1) {
            cellToFill.setSymbolIndex(possibleSymbols.getFirst());
            addStep(cellToFill, steps);
            if (this.solve(doku, steps)) {
                return true;
            }
        }

        while (!possibleSymbols.isEmpty()) {
            int nextPossibleSymbolIndex = rand.nextInt(possibleSymbols.size());
            int nextSymbol = possibleSymbols.get(nextPossibleSymbolIndex);

            cellToFill.setSymbolIndex(nextSymbol);
            addStep(cellToFill, steps);
            if (this.solve(doku, steps)) {
                return true;
            }
            cellToFill.setSymbolIndex(Cell.NOSYMBOL);
            addStep(cellToFill, steps);
            possibleSymbols.remove(nextPossibleSymbolIndex);

        }

        return false;
    }

}
