package sudoku.solver;

import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.logging.Level;

import gui.constants.Symbols;
import sudoku.io.SudokuPrinter;
import sudoku.structure.Cell;
import sudoku.structure.MultiDoku;
import sudoku.structure.Sudoku;

public class HumanSolver implements Solver {

	/**
	 * Résout le MultiDoku passé en paramètre, avec règles de déduction.
	 *
	 * @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) {
		if (Thread.interrupted())
			throw new CancellationException("User wants to stop the solver");

		Sudoku sudoku = doku.getSubGrid(0);
		logger.log(Level.FINE,
				'\n' + SudokuPrinter.toStringRectangleSudoku(sudoku,
						sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getBlockWidth(),
						sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getSize() / sudoku.getBlockWidth(),
						Symbols.Numbers));

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

		List<Cell> cellsToFill = doku.getEmptyCells();
		if (cellsToFill.isEmpty()) {
			return false;
		}

		for (Cell cellToFill : cellsToFill) {

			List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
			if (possibleSymbols.size() != 1) {
				continue;
			}

			cellToFill.setSymbolIndex(possibleSymbols.getFirst());
			addStep(cellToFill, steps);

			return this.solve(doku, steps);
		}

		return doku.isSolved();
	}

}
