package sudoku.io;

import gui.RenderableMultidoku;
import gui.constants.Symbols;
import sudoku.structure.Cell;
import sudoku.structure.MultiDoku;
import sudoku.structure.Sudoku;

import java.util.List;

public class SudokuPrinter {
	public static final String ANSI_RESET = "\u001B[0m";
	public static final String ANSI_RED = "\u001B[31m";
	public static final String ANSI_GREEN = "\u001B[32m";
	public static final String ANSI_YELLOW = "\u001B[33m";
	public static final String ANSI_BLUE = "\u001B[34m";
	public static final String ANSI_PURPLE = "\u001B[35m";
	public static final String ANSI_CYAN = "\u001B[36m";

	public static void printRectangleSudoku(final Sudoku s, int blockWidth, int blockHeight, Symbols symbols) {
		printRectangleSudoku(s, blockWidth, blockHeight, symbols.getSymbols());
	}

	public static void printRectangleSudoku(final Sudoku s, int blockWidth, int blockHeight, List<String> listSymbols) {
		for (int y = 0; y < s.getSize(); y++) {
			if (y % blockHeight == 0 && y > 0) {
				System.out.println();
			}
			StringBuilder line = new StringBuilder("[ ");
			for (int x = 0; x < s.getSize(); x++) {
				Cell c = s.getCell(x, y);
				if (c.getSymbolIndex() == Cell.NOSYMBOL) {
					line.append("  ");
				} else {
					line.append(listSymbols.get(c.getSymbolIndex())).append(" ");
				}
				if (x % blockWidth == blockWidth - 1 && x != blockWidth * blockHeight - 1) {
					line.append("| ");
				}
			}
			line.append("]");
			System.out.println(line);
		}
	}

	public static void printRectangleSudokuWithIndex(final Sudoku s, int blockWidth, int blockHeight,
			List<String> listSymbols) {
		StringBuilder header = new StringBuilder("");
		header.append("    ");
		for (int x = 0; x < blockWidth*blockHeight; x++) {
			header.append(x + 1).append(" ");
			if (x % blockWidth == blockWidth - 1 && x != blockWidth * blockHeight - 1) {
				header.append("  ");
			}
		}
		header.append("\n");
		System.out.println(header);
		for (int y = 0; y < s.getSize(); y++) {
			if (y % blockHeight == 0 && y > 0) {
				System.out.println();
			}
			StringBuilder line = new StringBuilder(y + 1);
			line.append(" [ ");
			for (int x = 0; x < s.getSize(); x++) {
				Cell c = s.getCell(x, y);
				if (c.getSymbolIndex() == Cell.NOSYMBOL) {
					line.append("  ");
				} else {
					line.append(listSymbols.get(c.getSymbolIndex())).append(" ");
				}
				if (x % blockWidth == blockWidth - 1 && x != blockWidth * blockHeight - 1) {
					line.append("| ");
				}
			}
			line.append("]");
			System.out.println(line);
		}
	}

	public static void printMultiDoku(final RenderableMultidoku rm, Symbols symbols, int blockWidth, int blockHeight) {
		printMultiDoku(rm, symbols.getSymbols(), blockWidth, blockHeight);
	}

	public static void printMultiDoku(final RenderableMultidoku rm, List<String> listSymbols, int blockWidth,
			int blockHeight) {
		StringBuilder line = new StringBuilder("\n");
		int nBlockInWidth = rm.getWidth() / blockWidth;
		for (int y = 0; y < rm.getHeight(); y++) {
			if (y % blockHeight == 0) {
				line.append("__".repeat(Math.max(0, rm.getWidth() + nBlockInWidth))).append("_\n");
			}
			line.append("[ ");
			for (int x = 0; x < rm.getWidth(); x++) {
				if (x % blockWidth == 0 && x > 0) {
					line.append("| ");
				}
				Cell cell = rm.getCell(x, y);
				if (cell != null) {
					if (cell.getSymbolIndex() == Cell.NOSYMBOL) {
						line.append("- ");
					} else {
						line.append(listSymbols.get(cell.getSymbolIndex())).append(" ");
					}
				} else {
					line.append("  ");
				}
			}
			line.append("]\n");
		}
		line.append("__".repeat(Math.max(0, rm.getWidth() + nBlockInWidth))).append("_\n");
		System.out.println(line);
	}

	public static void printMultiDokuWithIndex(final RenderableMultidoku rm, List<String> listSymbols, int blockWidth,
			int blockHeight) {
		StringBuilder line = new StringBuilder("\n");
		line.append("    ");
		for (int x = 0; x < rm.getWidth(); x++) {
			line.append(x + 1).append(" ");
			if (x % blockWidth == blockWidth - 1 && x != blockWidth * blockHeight - 1) {
				line.append("  ");
			}
		}
		line.append("\n");
		int nBlockInWidth = rm.getWidth() / blockWidth;
		for (int y = 0; y < rm.getHeight(); y++) {
			if (y % blockHeight == 0) {
				line.append("  ").append("__".repeat(Math.max(0, rm.getWidth() + nBlockInWidth))).append("_\n");
			}
			line.append(y+1).append(" [ ");
			for (int x = 0; x < rm.getWidth(); x++) {
				if (x % blockWidth == 0 && x > 0) {
					line.append("| ");
				}
				Cell cell = rm.getCell(x, y);
				if (cell != null) {
					if (cell.getSymbolIndex() == Cell.NOSYMBOL) {
						line.append("- ");
					} else {
						line.append(listSymbols.get(cell.getSymbolIndex())).append(" ");
					}
				} else {
					line.append("  ");
				}
			}
			line.append("]\n");
		}
		line.append("  ").append("__".repeat(Math.max(0, rm.getWidth() + nBlockInWidth))).append("_\n");
		System.out.println(line);
	}

	public static String toStringRectangleSudoku(final Sudoku s, int blockWidth, int blockHeight, Symbols symbols) {
		return toStringRectangleSudoku(s, blockWidth, blockHeight, symbols.getSymbols());
	}

	public static String toStringRectangleSudoku(final Sudoku s, int blockWidth, int blockHeight,
			List<String> listSymbols) {
		StringBuilder result = new StringBuilder();
		for (int y = 0; y < s.getSize(); y++) {
			// Ajouter une ligne vide entre les blocs horizontaux
			if (y % blockHeight == 0 && y > 0) {
				result.append("\n");
			}
			StringBuilder line = new StringBuilder("[ ");
			for (int x = 0; x < s.getSize(); x++) {
				// Ajouter la valeur de la cellule
				Cell cell = s.getCell(x, y);
				if (cell.getSymbolIndex() == Cell.NOSYMBOL) {
					line.append("  ");
				} else {
					line.append(listSymbols.get(cell.getSymbolIndex())).append(" ");
				}

				// Ajouter un séparateur vertical entre les blocs
				if (x % blockWidth == blockWidth - 1 && x != s.getSize() - 1) {
					line.append("| ");
				}
			}
			line.append("]");
			result.append(line).append("\n");
		}
		return result.toString();
	}

	public static void printMultiDoku(final MultiDoku doku, int blockWidth, int blockHeight, Symbols symbols) {
		if (doku.getNbSubGrids() == 1) {
			printRectangleSudoku(doku.getSubGrid(0), blockWidth, blockHeight, symbols);
		} else {
			printMultiDoku(RenderableMultidoku.fromMultidoku(doku), symbols, blockWidth, blockHeight);
		}
	}

	public static void printMultiDokuWithIndex(final MultiDoku doku, int blockWidth, int blockHeight, Symbols symbols) {
		if (doku.getNbSubGrids() == 1) {
			printRectangleSudokuWithIndex(doku.getSubGrid(0), blockWidth, blockHeight, symbols.getSymbols());
		} else {
			printMultiDokuWithIndex(RenderableMultidoku.fromMultidoku(doku), symbols.getSymbols(), blockWidth,
					blockHeight);
		}
	}

}
