import java.nio.file.Path;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;

public class GomokuGame {

    public static final int DEFAULT_BOARD_WIDTH = 15;  // largeur du plateau
    public static final int DEFAULT_BOARD_HEIGHT = 15; // hauteur du plateau
    public static final int DEFAULT_TOKENS_COUNT = 60; // nb de jetons

    private Player player1;
    private Player player2;

    private int boardWidth;
    private int boardHeight;
    private GomokuBoard board;

    Color colorP1;
    int currP;
    int nbTokens1, nbTokens2;

    public static void main(String[] args) {
        // Test
        GomokuGame g = new GomokuGame();
        System.out.println(g.load(Path.of(".cache/test.dat")));
        System.out.println(g.getBoard());
        System.out.println(g.save(Path.of(".cache/save.dat")));

        for (int i = 0; i < g.boardHeight; ++i) {
            for (int j = 0; j < g.boardWidth; ++j) {
                System.out.print(g.getBoard().get(i ,j));
            }
            System.out.println();
        }
    }

    public void newGame() {

    }

    public void startGame() {

    }

    public boolean save(Path filename) {
        // save the game state to the file
        // 1. Open the file
        // 2. Write the first line with:
        //      w h colorP1 currP nbTokens1 nbTokens2
        // 3. Write the next h lines with the board
        // 4. Close the file
        // 5. Return true if successful, false otherwise

        // if filename is null, save to default file in ".cache/save.dat"
        if (filename == null) {
            filename = Path.of(".cache/save.dat");
        }

        try (BufferedWriter writer = Files.newBufferedWriter(filename)) {
            // Write the first line
            writer.write(String.format("%d %d %s %d %d %d%n",
                    this.boardWidth, this.boardHeight, colorP1, currP, nbTokens1, nbTokens2));

            // Write the board
            for (int i = 0; i < boardHeight; ++i) {
                for (int j = 0; j < boardWidth; ++j) {
                    char c;
                    switch (board.get(i, j).getState()) {
                        case BLACK: c = 'X'; break;
                        case WHITE: c = 'O'; break;
                        case NIL:   c = '.'; break;
                        default: throw new IllegalStateException(
                            String.format("Unexpected value at cell (%d, %d): %s", i, j, board.get(i, j).getState())
                        );
                    }
                    writer.write(c);
                }
                writer.newLine();
            }
        } catch (IOException e) {
            System.err.println("Error writing file: " + e.getMessage());
            return false;
        } catch (Exception e) {
            System.err.println("Unexpected error: " + e.getMessage());
            return false;
        }
        return true;
    }

    public boolean load(Path filename) {
        // load the game state from the file
        // 1. Open the file
        // 2. Read the first line to get:
        //      w h colorP1 currP nbTokens1 nbTokens2
        // 3. Read the next h lines to get the board
        // 4. Close the file
        // 5. Initialize the board with the read values

        int w, h;
        Color[][] colors;

        try (BufferedReader reader = Files.newBufferedReader(filename)) {
            String line = reader.readLine();
            if (line == null) {
                throw new IOException("Empty save file");
            }

            String[] parts = line.split(" ");
            if (parts.length != 6) {
                throw new IOException("Invalid save file format");
            }
            w = Integer.parseInt(parts[0]);
            h = Integer.parseInt(parts[1]);
            colorP1 = Color.valueOf(parts[2]);
            currP = Integer.parseInt(parts[3]);
            nbTokens1 = Integer.parseInt(parts[4]);
            nbTokens2 = Integer.parseInt(parts[5]);

            if (w <= 0 || h <= 0) {
                throw new IllegalArgumentException("Invalid board dimensions");
            }

            colors = new Color[h][w];

            for (int i = 0; i < h; ++i) {
                line = reader.readLine();
                if (line == null) {
                    throw new IOException("Unexpected end of file");
                }

                if (line.length() != w) {
                    throw new IOException("Invalid board line format");
                }

                for (int j = 0; j < w; ++j) {
                    switch (line.charAt(j)) {
                        case 'X': colors[i][j] = Color.BLACK; break;
                        case 'O': colors[i][j] = Color.WHITE; break;
                        case '.': colors[i][j] = Color.NIL;   break;
                        default:
                            throw new IllegalArgumentException("Invalid color: " + line.charAt(j));
                    }
                }
            }

        } catch (IOException e) {
            System.err.println("Error reading file: " + e.getMessage());
            return false;
        } catch (NumberFormatException e) {
            System.err.println("Invalid number format: " + e.getMessage());
            return false;
        } catch (IllegalArgumentException e) {
            System.err.println("Invalid color format: " + e.getMessage());
            return false;
        } catch (Exception e) {
            System.err.println("Unexpected error: " + e.getMessage());
            return false;
        }

        // Initialize the board with the read values
        this.boardWidth  = w;
        this.boardHeight = h;
        this.board = new GomokuBoard(w, h, colors);

        return true;
    }

    public GomokuBoard getBoard() {
        return this.board;
    }
}
