package gui;

import java.util.ArrayList;
import java.util.List;

import common.Signal;
import imgui.ImGui;
import imgui.extension.imguifiledialog.ImGuiFileDialog;
import imgui.extension.imguifiledialog.flag.ImGuiFileDialogFlags;
import imgui.type.ImBoolean;
import imgui.type.ImInt;
import sudoku.constraint.Constraint;
import sudoku.structure.Difficulty;
import sudoku.structure.MultiDoku;
import sudoku.structure.SudokuFactory;

public class SudokuSelector {

	public final Signal onSelect = new Signal();
	private MultiDoku doku;

	private final boolean canGenEmptyGrid;

	private final ImInt sudokuType = new ImInt(0);

	private final ImInt difficulty = new ImInt(Difficulty.Medium.ordinal());
	private final List<ImBoolean> contraints = new ArrayList<>();

	private static final String[] sudokuTypes = { "Carré", "Rectangle", "Multidoku" };
	private static final int SQUARE = 0, RECTANGLE = 1, MULTIDOKU = 2;

	private final ImInt sudokuSize = new ImInt(3);

	private final ImInt sudokuWidth = new ImInt(3);
	private final ImInt sudokuHeight = new ImInt(3);

	public SudokuSelector(boolean canGenEmptyGrid) {
		this.canGenEmptyGrid = canGenEmptyGrid;
		initConstraints();
	}

	private List<Constraint> getConstraints() {
		List<Constraint> constraints = new ArrayList<>();
		for (int i = 0; i < this.contraints.size(); i++) {
			if (this.contraints.get(i).get())
				constraints.add(Constraint.values()[i]);
		}
		return constraints;
	}

	private void initConstraints() {
		for (Constraint cons : Constraint.values()) {
			contraints.add(new ImBoolean(SudokuFactory.DEFAULT_CONSTRAINTS.contains(cons)));
		}
	}

	private void selectSudoku(MultiDoku doku, boolean empty) {
		this.doku = doku;
		if (!empty) {
			try {
				SudokuFactory.fillDoku(doku, Difficulty.values()[difficulty.get()]);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		this.onSelect.emit();
	}

	public void renderFileDialog() {
		if (ImGuiFileDialog.display("browse-sudoku", ImGuiFileDialogFlags.None)) {
			if (ImGuiFileDialog.isOk()) {
				var selection = ImGuiFileDialog.getSelection();
				for (var entry : selection.entrySet()) {
					try {
						String filePath = entry.getValue();
						this.doku = SudokuFactory.fromfile(filePath);
						if (this.doku != null)
							this.onSelect.emit();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
			ImGuiFileDialog.close();
		}
	}

	public void render() {
		ImGui.combo("Type de Sudoku", sudokuType, sudokuTypes);
		ImGui.combo("Difficulté", difficulty, Difficulty.getDifficultyNames());
		if (ImGui.treeNode("Constraintes")) {
			for (Constraint cons : Constraint.values()) {
				ImGui.checkbox(cons.getDisplayName(), contraints.get(cons.ordinal()));
			}
			ImGui.treePop();
		}
		switch (sudokuType.get()) {
			case SQUARE:
				ImGui.inputInt("Taille", sudokuSize);
				if (ImGui.button("Résoudre un sudoku")) {
					selectSudoku(SudokuFactory.createBasicEmptySquareDoku(sudokuSize.get(), getConstraints()), false);
				}
				if (canGenEmptyGrid && ImGui.button("Générer une grille vide")) {
					selectSudoku(SudokuFactory.createBasicEmptySquareDoku(sudokuSize.get(), getConstraints()), true);
				}
				break;

			case RECTANGLE:
				ImGui.inputInt("Largeur", sudokuHeight);
				ImGui.inputInt("Longueur", sudokuWidth);
				if (ImGui.button("Résoudre un sudoku")) {
					selectSudoku(
							SudokuFactory.createBasicEmptyRectangleDoku(sudokuWidth.get(), sudokuHeight.get(),
									getConstraints()),
							false);
				}
				if (canGenEmptyGrid && ImGui.button("Générer une grille vide")) {
					selectSudoku(
							SudokuFactory.createBasicEmptyRectangleDoku(sudokuWidth.get(), sudokuHeight.get(),
									getConstraints()),
							true);
				}
				break;

			case MULTIDOKU:
				ImGui.inputInt("Taille", sudokuSize);
				if (ImGui.button("Résoudre un sudoku")) {
					selectSudoku(SudokuFactory.createBasicXShapedMultidoku(sudokuSize.get(), getConstraints()), false);
				}
				if (canGenEmptyGrid && ImGui.button("Générer une grille vide")) {
					selectSudoku(SudokuFactory.createBasicXShapedMultidoku(sudokuSize.get(), getConstraints()), true);
				}

			default:
				break;
		}
		if (ImGui.button("À partir d'un fichier")) {
			ImGuiFileDialog.openDialog("browse-sudoku", "Choisissez un fichier", ".json", ".");
		}
		renderFileDialog();
	}

	public MultiDoku getDoku() {
		return doku;
	}

}
