#include <stdlib.h>
#include <stdio.h>

#include "board.h"
#include "coordinate.h"
#include "piece.h"

static Board _setup_colors(Board b) {
    short i, j;
    
    for (i = 0; i < SIZE; i++)
        for (j = 0; j < SIZE; j++)
            if (i % 2)
                if (j % 2)
                    b[i][j].color = BLACK;
                else
                    b[i][j].color = WHITE;
            else
                if (j % 2)
                    b[i][j].color = WHITE;
                else
                    b[i][j].color = BLACK;

    return b;
}

static Board _set_new_piece(Board b, Coord c, Color color, PieceType t) {
    Square s = board_get_square(b, c);
    s.piece = new_piece(color, t);

    return board_set_square(b, c, s);
}

static Board _pawns(Board b) {
    Coord c = coord_set_row(coord_null(), '2');
    char col;

    for (col = 'a'; col <= 'h'; col++)
        _set_new_piece(b, coord_set_col(c, col), WHITE, PAWN);

    c = coord_set_row(coord_null(), '7');
    for (col = 'a'; col <= 'h'; col++)
        _set_new_piece(b, coord_set_col(c, col), BLACK, PAWN);

    return b;
}

static Board _rocks(Board b) {
    _set_new_piece(b, coord_init("a1"), WHITE, ROCK);
    _set_new_piece(b, coord_init("h1"), WHITE, ROCK);
    _set_new_piece(b, coord_init("a8"), BLACK, ROCK);
    _set_new_piece(b, coord_init("h8"), BLACK, ROCK);

    return b;
}

static Board _knights(Board b) {
    _set_new_piece(b, coord_init("b1"), WHITE, KNIGHT);
    _set_new_piece(b, coord_init("g1"), WHITE, KNIGHT);
    _set_new_piece(b, coord_init("b8"), BLACK, KNIGHT);
    _set_new_piece(b, coord_init("g8"), BLACK, KNIGHT);

    return b;
}

static Board _bishops(Board b) {
    _set_new_piece(b, coord_init("c1"), WHITE, BISHOP);
    _set_new_piece(b, coord_init("f1"), WHITE, BISHOP);
    _set_new_piece(b, coord_init("c8"), BLACK, BISHOP);
    _set_new_piece(b, coord_init("f8"), BLACK, BISHOP);

    return b;
}

static Board _queens(Board b) {
    _set_new_piece(b, coord_init("d1"), WHITE, QUEEN);
    _set_new_piece(b, coord_init("d8"), BLACK, QUEEN);

    return b;
}

static Board _kings(Board b) {
    _set_new_piece(b, coord_init("e1"), WHITE, KING);
    _set_new_piece(b, coord_init("e8"), BLACK, KING);

    return b;
}

static Board _setup_pieces(Board b) {
    return _pawns(_rocks(_knights(_bishops(_queens(_kings(b)))))); // :-)
}

static Board _initial_setup(Board b) {
    return _setup_pieces(_setup_colors(b));
}

static short _from_col(char col) {
    // col is a character between 'a' and 'h'
    return col - 'a';
}

static short _from_row(char row) {
    // row is an ASCII digit between '1' and '8'
    return row - '1';
}

Board board_init() {
    int i, j;

    Board b = malloc(sizeof(Square*) * SIZE);
    
    for (i = 0; i < SIZE; i++) {
        b[i] = malloc(sizeof(Square) * SIZE);
        for (j = 0; j < SIZE; j++)
            b[i][j].piece = NULL;
    }

    return _initial_setup(b);
}

int board_delete(Board b) {
    short i, j;

    for (i = 0; i < SIZE; i++) {
        for (j = 0; j < SIZE; j++)
            if (b[i][j].piece != NULL)
                free(b[i][j].piece);
        free(b[i]);
    }

    free(b);

    return 0;
}

Square board_get_square(Board b, Coord c) {
    short x = _from_col(c.col);
    short y = _from_row(c.row);

    return b[x][y];
}

Board board_set_square(Board b, Coord c, Square s) {
    short x = _from_col(c.col);
    short y = _from_row(c.row);

    b[x][y] = s;

    return b;
}