const Grid = @import("grid.zig");
const Piece = @import("piece.zig");

pub fn moveRight(grid: Grid, piece: Piece) Piece {
    var new_piece = piece;
    new_piece.col += 1;
    if (checkCollision(grid, new_piece)) {
        return piece;
    } else {
        return new_piece;
    }
}

pub fn moveLeft(grid: Grid, piece: Piece) Piece {
    var new_piece = piece;
    new_piece.col -= 1;
    if (checkCollision(grid, new_piece)) {
        return piece;
    } else {
        return new_piece;
    }
}

pub fn moveDown(grid: Grid, piece: Piece) Piece {
    var new_piece = piece;
    new_piece.row += 1;
    if (checkCollision(grid, new_piece)) {
        new_piece.row -= 1;
        new_piece.dropped = true;
        return new_piece;
    } else {
        return new_piece;
    }
}

pub fn hardDrop(grid: Grid, piece: Piece) Piece {
    var new_piece = piece;
    while (!new_piece.dropped) {
        new_piece = moveDown(grid, new_piece);
    }
    return new_piece;
}

pub fn drop(grid: Grid, piece: Piece) Grid {
    var new_grid = grid;

    for (piece.structure) |_, y| {
        for (piece.structure[y]) |_, x| {
            if (piece.structure[y][x]) {

                new_grid.cells[@intCast(usize, piece.row + @intCast(i32, y))][@intCast(usize, piece.col + @intCast(i32, x))].free = false;
                new_grid.cells[@intCast(usize, piece.row + @intCast(i32, y))][@intCast(usize, piece.col + @intCast(i32, x))].color = piece.color;
            }
        }
    }

    return new_grid;
}

pub fn shadow(grid: Grid, piece: Piece) Piece {
    var new_shadow = hardDrop(grid, piece);
    return new_shadow;
}

fn checkCollision(grid: Grid, piece: Piece) bool {
    for (piece.structure) |_, y| {
        for (piece.structure[y]) |_, x| {
            if (piece.structure[y][x] and ((@intCast(i32, x) + piece.col > Grid.ncolumns - 1) or
                                               (@intCast(i32, x) + piece.col < 0) or (@intCast(i32, y) + piece.row > Grid.nrows - 1) or
                                               (!grid.cells[@intCast(usize, piece.row + @intCast(i32, y))][@intCast(usize, piece.col + @intCast(i32, x))].free)))
            {
                return true;
            }
        }
    }
    return false;
}

pub fn rotateLeft(grid: Grid, piece: Piece) Piece {
    var new_piece = piece.rotate(Piece.Rot.left);
    if (checkCollision(grid, new_piece)) {
        return piece;
    }
    return new_piece;
}

pub fn rotateRight(grid: Grid, piece: Piece) Piece {
    var new_piece = piece.rotate(Piece.Rot.right);
    if (checkCollision(grid, new_piece)) {
        return piece;
    }
    return new_piece;
}
