package com.wvu.ai.csp.project.SudokuSolver;

import aima.core.search.csp.CSP;
import aima.core.search.csp.Domain;
import aima.core.search.csp.Variable;
import java.util.LinkedList;
import java.util.List;

public class SudokuCSP extends CSP {

	private static final Object[] DOMAIN_VALUES = new Object[]{1, 2, 3, 4, 5, 6, 7, 8, 9};

	public SudokuCSP(Board sudokuBoard) {
		loadVariables(sudokuBoard);
		generateRowConstraints(sudokuBoard);
		generateColumnConstraints(sudokuBoard);
		generateRegionConstraints(sudokuBoard);
	}

	private void loadVariables(Board sudokuBoard) {
		for (CellCollection row : sudokuBoard.getRows()) {
			for (Cell cell : row.getCollection()) {
				Variable newVariable = new Variable(cell.getName());
				addVariable(newVariable);
				if (cell.isAssigned()) {
					setDomain(newVariable, new Domain(new Object[]{}));
				} else {
					setDomain(newVariable, new Domain(DOMAIN_VALUES));
				}
			}
		}
	}

	private void generateRowConstraints(Board sudokuBoard) {
		List<Variable> cellVariables = getVariables();
		int sudokuBoardSideSize = sudokuBoard.getSize();
		for (int rowNum = 0; rowNum < cellVariables.size(); rowNum += sudokuBoardSideSize) {
			List<Variable> rowVariables = new LinkedList<>();
			for (int colNum = 0; colNum < sudokuBoardSideSize; colNum++) {
				rowVariables.add(cellVariables.get(rowNum + colNum));
			}
			addConstraint(new CellCollectionConstraint(rowVariables));
		}
	}

	private void generateColumnConstraints(Board sudokuBoard) {
		List<Variable> cellVariables = getVariables();
		int sudokuBoardSideSize = sudokuBoard.getSize();
		for (int colNum = 0; colNum < sudokuBoardSideSize; colNum++) {
			List<Variable> colVariables = new LinkedList<>();
			for (int rowNum = 0; rowNum < cellVariables.size(); rowNum += sudokuBoardSideSize) {
				colVariables.add(cellVariables.get(rowNum + colNum));
			}
			addConstraint(new CellCollectionConstraint(colVariables));
		}
	}

	private void generateRegionConstraints(Board sudokuBoard) {
		List<Variable> cellVariables = getVariables();
		int sudokuBoardSideSize = sudokuBoard.getSize();
		int sudokuRegionSideSize = (int)Math.sqrt(sudokuBoardSideSize);
		for (int i = 0; i < cellVariables.size(); i += sudokuBoardSideSize * sudokuRegionSideSize) {
			for (int j = 0; j < sudokuBoardSideSize; j += sudokuRegionSideSize) {
				List<Variable> regionVariables = new LinkedList<>();
				int verticalIteration = 0;
				// ((rowNum / sudokuBoardSideSize) - (sudokuRegionSideSize * verticalIteration))
				for (int rowNum = i; verticalIteration < sudokuRegionSideSize; rowNum += sudokuBoardSideSize) {
					int horizontalIteration = 0;
					// (colNum - (sudokuRegionSideSize * horizontalIteration))
					for (int colNum = j; horizontalIteration < sudokuRegionSideSize; colNum++) {
						regionVariables.add(cellVariables.get(rowNum + colNum));
						horizontalIteration++;
					}
					verticalIteration++;
				}
				addConstraint(new CellCollectionConstraint(regionVariables));
			}
		}
	}

}

@@ -250,15 +250,8 @@
 ate 
-static 
 fina
@@ -265,104 +265,278 @@
 t%5B%5D 
-DOMAIN_VALUES = new Object%5B%5D%7B1, 2, 3, 4, 5, 6, 7, 8, 9%7D;%0A%0A%09public S
+domainValues;%0A%0A%09public SudokuCSP(Board sudokuBoard) %7B%0A%09%09LinkedList%3CObject%3E possibleValues = new LinkedList%3C%3E();%0A%09%09for (int i = 1; i %3C= s
 udoku
-CSP(
 Board
- sudokuBoard) %7B
+.getSize(); i++) %7B%0A%09%09%09possibleValues.add(i);%0A%09%09%7D%0A%09%09domainValues = possibleValues.toArray(new Object%5BpossibleValues.size()%5D);
 %0A%09%09l
@@ -1063,21 +1063,20 @@
 ain(
-DOMAIN_VALUES
+domainValues
 ));%0A

Fix domain value generation to be variable based on board size