import csv
from sudoku import *
from time import time


def example():
    # Example how to use the solver.
    # First you have to save your sudoku as an Array2D type.
    # You can either start with an empty Array2D and fill the values by position
    # (e.g. if you parse the data from a file):
    quiz = Array2D(9, 9)
    quiz[1, 1] = 1  # indexing starts at 1
    # Or you can construct the Array with a list of integers:
    quiz = [2, 9, 4, 5, 1, 3, 0, 0, 6,
            6, 0, 0, 8, 4, 2, 3, 1, 9,
            3, 0, 0, 6, 9, 7, 2, 5, 4,
            0, 0, 0, 0, 5, 6, 0, 0, 0,
            0, 4, 0, 0, 8, 0, 0, 6, 0,
            0, 0, 0, 4, 7, 0, 0, 0, 0,
            7, 3, 0, 1, 6, 4, 0, 0, 5,
            9, 0, 0, 7, 3, 5, 0, 0, 1,
            4, 0, 0, 9, 2, 8, 6, 3, 7]
    quiz = Array2D(9, 9, quiz)

    # Then you can convert the Array to a Sudoku type and solve it:
    quiz = Sudoku(quiz)
    quiz.solve()
    print(quiz)

    # You can retrieve the solved sudoku as a list of integers:
    quiz = quiz.get_grid()
    print(quiz)


def demo():
    # Shows the capability of the solver using some example sudokus of different difficulties.

    # Some example 9x9 sudokus
    counter = 0
    for quiz, solution, description in get_quiz("data/demo.csv"):
        counter += 1
        if description:
            print("Quiz: {}:".format(description))
        else:
            print("Quiz:")
        print(quiz)
        quiz.solve()
        if quiz == solution:
            print("The sudoku was solved successfully. Solution:")
            print(quiz)
        else:
            print("Could not solve sudoku number {}. Calculated solution:".format(counter))
            print(quiz)
            print("Correct Solution")
            print(solution)
        print("-------------------------------------------------------------------")

    # The solver works on sudokus of any size. Here we have a 16x16 sudoku
    quiz = "1 0 0 2 13 8 4 0 0 10 14 6 3 0 0 5" + " 0 12 0 0 0 2 0 0 0 0 0 0 0 0 0 14"
    quiz += " 0 0 16 7 10 15 14 1 0 2 0 0 0 0 9 4" + " 0 0 0 9 0 0 0 0 5 15 16 0 0 8 0 0"
    quiz += " 0 0 0 15 0 3 0 0 0 11 9 0 0 0 7 16" + " 4 0 0 0 0 0 0 0 1 16 10 0 0 0 0 0"
    quiz += " 0 0 9 0 14 1 0 16 0 7 6 2 5 0 8 0" + " 6 0 2 0 11 0 15 0 8 0 12 0 9 1 0 0"
    quiz += " 0 0 12 14 0 4 0 3 0 5 0 16 0 9 0 11" + " 0 1 0 10 15 14 9 0 6 0 7 12 0 3 0 0"
    quiz += " 0 0 0 0 0 10 16 11 0 0 0 0 0 0 0 12" + " 9 16 0 0 0 7 12 0 0 0 11 0 1 0 0 0"
    quiz += " 0 0 10 0 0 16 8 4 0 0 0 0 6 0 0 0" + " 16 14 0 0 0 0 10 0 2 9 13 3 4 11 0 0"
    quiz += " 15 0 0 0 0 0 0 0 0 0 5 0 0 0 12 0" + " 13 0 0 8 9 11 5 0 0 4 15 10 2 0 0 1"

    solution = "1 11 15 2 13 8 4 9 7 10 14 6 3 12 16 5" + " 8 12 13 6 16 2 7 5 9 3 4 11 15 10 1 14"
    solution += " 3 5 16 7 10 15 14 1 12 2 8 13 11 6 9 4" + " 10 4 14 9 3 12 11 6 5 15 16 1 13 8 2 7"
    solution += " 14 8 1 15 4 3 6 10 13 11 9 5 12 2 7 16" + " 4 7 5 3 12 9 2 8 1 16 10 15 14 13 11 6"
    solution += " 12 10 9 11 14 1 13 16 3 7 6 2 5 4 8 15" + " 6 13 2 16 11 5 15 7 8 14 12 4 9 1 10 3"
    solution += " 7 15 12 14 6 4 1 3 10 5 2 16 8 9 13 11" + " 5 1 11 10 15 14 9 13 6 8 7 12 16 3 4 2"
    solution += " 2 6 8 13 5 10 16 11 4 1 3 9 7 14 15 12" + " 9 16 3 4 8 7 12 2 15 13 11 14 1 5 6 10"
    solution += " 11 9 10 5 2 16 8 4 14 12 1 7 6 15 3 13" + " 16 14 7 12 1 6 10 15 2 9 13 3 4 11 5 8"
    solution += " 15 2 4 1 7 13 3 14 11 6 5 8 10 16 12 9" + " 13 3 6 8 9 11 5 12 16 4 15 10 2 7 14 1"

    quiz = quiz.split()
    quiz = [int(i) for i in quiz]
    start = time()
    quiz = Sudoku(Array2D(16, 16, quiz))
    end = time()
    print(end - start)

    solution = solution.split()
    solution = [int(i) for i in solution]
    solution = Sudoku(Array2D(16, 16, solution))

    print("Quiz: 16x16 Sudoku:")
    print(quiz)
    start = time()
    quiz.solve()
    end = time()
    print(end - start)
    if quiz == solution:
        print("The sudoku was solved successfully. Solution:")
        print(quiz)


def get_quiz(filename, n=float("inf")) -> tuple:
    """ :returns the first n tuples of sudoku quiz, solution and a description of the puzzle, if one is given.
        If no number n is given, then all the quizzes and solutions from the file are read.
        Works only for 4x4 and 9x9 sudokus (for bigger ones the file format has to be changed). """
    file = open(filename, "r")
    reader = csv.reader(file, delimiter=',')
    next(reader)  # jump over header
    for row in reader:
        if reader.line_num - 1 > n:
            break
        # find out the size of the sudoku
        size = row[0].find(' ')
        # remove spaces and convert to list
        quiz = list((row[0]).replace(" ", ""))
        solution = list((row[1]).replace(" ", ""))
        # convert char's in the list to int's
        quiz = [int(i) for i in quiz]
        solution = [int(i) for i in solution]
        # build Sudoku's
        quiz = Sudoku(Array2D(size, size, quiz))
        solution = Sudoku(Array2D(size, size, solution))
        # check if there is a description present
        if len(row) > 2:
            description = row[2].strip()
        else:
            description = None

        yield quiz, solution, description


if __name__ == '__main__':
    # example()
    demo()
