#include <stdio.h>
#include <string.h>

#include "board.h"

#define LINE_SIZE 16

// Pasa una línea a una fila. La línea debe tener exactamente 9 dígitos.
static int parse_row(const char *line, int *row) {
    size_t length = strcspn(line, "\r\n");
    if (length != BOARD_SIZE) {
        return 0;
    }
    for (int i = 0; i < BOARD_SIZE; i++) {
        if (line[i] < '0' || line[i] > '9') {
            return 0;
        }
        row[i] = line[i] - '0';
    }
    return 1;
}

int board_load(const char *path, Board *board) {
    FILE *file = fopen(path, "r");
    if (file == NULL) {
        return 0;
    }
    char line[LINE_SIZE];
    int ok = 1;
    for (int row = 0; ok && row < BOARD_SIZE; row++) {
        if (fgets(line, sizeof(line), file) == NULL || !parse_row(line, board->cells[row])) {
            ok = 0;
        }
    }
    // Después de la última fila no debe haber nada más.
    if (ok && fgets(line, sizeof(line), file) != NULL) {
        ok = 0;
    }
    fclose(file);
    return ok;
}

void board_print(const Board *board) {
    for (int row = 0; row < BOARD_SIZE; row++) {
        for (int column = 0; column < BOARD_SIZE; column++) {
            printf("%d", board->cells[row][column]);
        }
        printf("\n");
    }
}

int board_can_place(const Board *board, int row, int column, int digit) {
    for (int i = 0; i < BOARD_SIZE; i++) {
        if (i != column && board->cells[row][i] == digit) {
            return 0;
        }
        if (i != row && board->cells[i][column] == digit) {
            return 0;
        }
    }
    int first_row = row - row % 3;
    int first_column = column - column % 3;
    for (int r = first_row; r < first_row + 3; r++) {
        for (int c = first_column; c < first_column + 3; c++) {
            if ((r != row || c != column) && board->cells[r][c] == digit) {
                return 0;
            }
        }
    }
    return 1;
}

int board_is_legal(const Board *board) {
    for (int row = 0; row < BOARD_SIZE; row++) {
        for (int column = 0; column < BOARD_SIZE; column++) {
            int digit = board->cells[row][column];
            if (digit != 0 && !board_can_place(board, row, column, digit)) {
                return 0;
            }
        }
    }
    return 1;
}
