#include "board.h"

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

// Alcanza para 9 dígitos, el salto de línea, el '\0', y uno más: así se nota una línea larga.
#define LINE_SIZE (BOARD_SIZE + 3)

// Pasa una línea a una fila del tablero. Devuelve 0 si no son exactamente 9 dígitos.
static int parse_row(char *line, int *row) {
    size_t length = strlen(line);
    if (length > 0 && line[length - 1] == '\n') {
        line[length - 1] = '\0';
        length--;
    }
    if (length != BOARD_SIZE) {
        return 0;
    }
    for (int col = 0; col < BOARD_SIZE; col++) {
        if (line[col] < '0' || line[col] > '9') {
            return 0;
        }
        row[col] = line[col] - '0';
    }
    return 1;
}

static int read_rows(FILE *file, Board *board) {
    char line[LINE_SIZE];
    for (int row = 0; row < BOARD_SIZE; row++) {
        if (fgets(line, sizeof line, file) == NULL || !parse_row(line, board->cells[row])) {
            return 0;
        }
    }
    // Después de la fila 9 no puede venir nada más.
    return fgets(line, sizeof line, file) == NULL;
}

int board_load(const char *path, Board *board) {
    FILE *file = fopen(path, "r");
    if (file == NULL) {
        return 0;
    }
    int ok = read_rows(file, board);
    fclose(file);
    return ok;
}

// ¿Otra celda de la misma fila, columna o caja tiene el dígito de (row, col)?
static int is_repeated(const Board *board, int row, int col) {
    int digit = board->cells[row][col];
    int box_row = row - row % BOX_SIZE;
    int box_col = col - col % BOX_SIZE;
    for (int i = 0; i < BOARD_SIZE; i++) {
        if (i != col && board->cells[row][i] == digit) {
            return 1;
        }
        if (i != row && board->cells[i][col] == digit) {
            return 1;
        }
        int other_row = box_row + i / BOX_SIZE;
        int other_col = box_col + i % BOX_SIZE;
        if ((other_row != row || other_col != col) && board->cells[other_row][other_col] == digit) {
            return 1;
        }
    }
    return 0;
}

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

void board_print(const Board *board) {
    for (int row = 0; row < BOARD_SIZE; row++) {
        if (row > 0 && row % BOX_SIZE == 0) {
            printf("------+-------+------\n");
        }
        for (int col = 0; col < BOARD_SIZE; col++) {
            if (col > 0 && col % BOX_SIZE == 0) {
                printf("| ");
            }
            if (board->cells[row][col] == 0) {
                printf(". ");
            } else {
                printf("%d ", board->cells[row][col]);
            }
        }
        printf("\n");
    }
}
