package sudoku.io;

import sudoku.constraint.*;
import sudoku.solver.Solver;
import sudoku.structure.Difficulty;
import sudoku.structure.MultiDoku;
import sudoku.structure.Sudoku;
import sudoku.structure.SudokuFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;

public class ConsoleInterface {
    public Scanner reader = new Scanner(System.in);

    public void start(){
        welcome();
        System.out.println("First of all, you need to tell me the size of the sudoku you want to generate.");
        int width = getBlockWidth();
        int height = getBlockHeight();
        System.out.println("Your sudoku will have blocks of a " + width + " x " + height + " format.");
        int numberOfSymbols = width * height;
        System.out.println("Would you like to pick the " + numberOfSymbols + " symbols from the sudoku? (y/n, default 'no' will use numbers)" );
        List<String> listSymbols = new ArrayList<>();
        if(reader.next().equalsIgnoreCase("y")){
            pickSymbols(listSymbols, numberOfSymbols);
        }
        else {
            // TODO
            System.out.println("Simon doit finir sa partie.");
            assert false;
        }
        List<Constraint> listConstraints = getListConstraints();


        System.out.println("Now that we have the size of our sudoku, would you rather have a single grid ('one', default), " +
                "or a a multidoku composed of 5 subgrids ('multi') ?");
        List<Sudoku> subGrids = new ArrayList<>();
        MultiDoku doku;
        if (reader.next().equalsIgnoreCase("multi")) {
            doku = SudokuFactory.createBasicEmptyRectangleDoku(width, height, listConstraints);
        }
        else {
            doku = SudokuFactory.createBasicXShapedMultidoku(width, height, listConstraints);
        }
        System.out.println("Your sudoku will look like this:");
        // TODO printMultiDoku method not yet implemented
        SudokuPrinter.printMultiDoku(doku, width, height);
        System.out.println("We now will fill this sudoku.");
        System.out.println("What level of difficulty would you like? ('very easy', 'easy', 'medium' (default), 'hard', 'full' (sudoku fully completed))");
        String difficulty = reader.next().toLowerCase();
        if (difficulty.equals("full")) {
            generateFullDoku(doku);
        }
        else {
            generatePartialDoku(doku, difficulty);
        }
        System.out.println("Here's your sudoku !");
        SudokuPrinter.printMultiDoku(doku, width, height);
    }

    public void welcome(){
        System.out.println("Welcome to our Sudoku Solver!");
        System.out.println("This is the project of Melvyn Bauvent, Lilas Grenier and Simon Priblyski.");
    }

    public int getBlockWidth() {
        System.out.println("Width of a block: ");
        int widthBlock = reader.nextInt();
        checkValidSize(widthBlock);
        while (!checkValidSize(widthBlock)) {
            System.out.println("That is not a valid width for a block. Try again:");
            widthBlock = reader.nextInt();
        }
        System.out.println("You have chose a width of " + widthBlock + ".");
        return widthBlock;
    }

    public int getBlockHeight() {
        System.out.println("Height of a block: ");
        int heightBlock = reader.nextInt();
        checkValidSize(heightBlock);
        while (!checkValidSize(heightBlock)) {
            System.out.println("That is not a valid height for a block. Try again:");
            heightBlock = reader.nextInt();
        }
        System.out.println("You have chose a height of " + heightBlock + ".");
        return heightBlock;
    }

    private Boolean checkValidSize(int size) {
        return (size > 0);
    }

    private void pickSymbols(List<String> listSymbols, int numberOfSymbols) {
        System.out.println("You have chosen to pick your own symbols.");
        for (int i = 0; i < numberOfSymbols; i++) {
            System.out.println("Choose for the symbol number " + i + ": ");
            String newSymbol = reader.next();
            while (listSymbols.contains(newSymbol)) {
                System.out.println("This symbol has already been given. Try again:");
                newSymbol = reader.next();
            }
            listSymbols.add(newSymbol);
        }
        System.out.println("You chose the symbols: " + listSymbols.toString());
    }

    private List<Constraint> getListConstraints() {
        List<Constraint> listConstraints = SudokuFactory.DEFAULT_CONSTRAINTS;
        System.out.println("The sudoku have constraints of blocks, lines and columns. Would you like to add the diagonal constraints ? (y/n, default 'no')");
        if(reader.next().equalsIgnoreCase("y")){
            listConstraints.add(Constraint.Diagonal);
        }
        return listConstraints;
    }

    private void generatePartialDoku(MultiDoku doku, String difficultyName) {
        Difficulty difficulty;
        switch (difficultyName){
            case "very easy": difficulty = Difficulty.VeryEasy;
            case "easy": difficulty = Difficulty.Easy;
            case "hard": difficulty = Difficulty.Hard;
            default: difficulty = Difficulty.Medium;
        }
        try {
            SudokuFactory.fillDoku(doku, difficulty);
        } catch (Exception e) {
            System.out.println("There seems to be a problem with those settings. Let's start again.");
        }
    }

    private void generateFullDoku(MultiDoku doku) {
        Solver.solveRandom(doku, new Random());
    }

}
