#include "board.h"

std::vector<Move> getLegalMoves(const Board& board, bool isBlack) {
    std::uint64_t player = isBlack ? board.black : board.white;
    std::uint64_t opponent = isBlack ? board.white : board.black;
    std::uint64_t empty = ~(board.black | board.white);

    std::uint64_t moves = 0;

    const std::uint64_t notAFile = 0xfefefefefefefefeULL;
    const std::uint64_t notHFile = 0x7f7f7f7f7f7f7f7fULL;

    const int shifts[8] = {1, -1, 8, -8, 9, -9, 7, -7};
    const std::uint64_t masks[8] = {notAFile, notHFile, 0xffffffffffffffffULL, 0xffffffffffffffffULL,
                                    notAFile, notHFile, notHFile, notAFile};

    for(int dir=0; dir<8; dir++) {
        std::uint64_t maskDir = masks[dir];
        std::int64_t shift = shifts[dir];

        std::uint64_t t;
        if(shift > 0) t = (player << shift) & opponent & maskDir;
        else          t = (player >> (-shift)) & opponent & maskDir;

        std::uint64_t potential = t;
        for(int i=0;i<5;i++) {
            if(shift > 0) t = (t << shift) & opponent & maskDir;
            else          t = (t >> (-shift)) & opponent & maskDir;
            potential |= t;
        }

        if(shift > 0) moves |= (potential << shift) & empty & maskDir;
        else          moves |= (potential >> (-shift)) & empty & maskDir;
    }

    std::vector<Move> result;
    for(int y=0;y<8;y++) {
        for(int x=0;x<8;x++) {
            if(moves & mask(x,y)) result.push_back({x,y});
        }
    }
    //std::cout << "moves bitboard: " << std::hex << moves << std::dec << std::endl;
    //std::cout << "result size: " << result.size() << std::endl;
    return result;
}

void playMove(Board& board, bool isBlack, int x, int y) {
    std::uint64_t player = isBlack ? board.black : board.white;
    std::uint64_t opponent = isBlack ? board.white : board.black;

    std::uint64_t moveMask = mask(x,y);
    std::uint64_t flips = 0;

    const std::uint64_t notAFile = 0xfefefefefefefefeULL;
    const std::uint64_t notHFile = 0x7f7f7f7f7f7f7f7fULL;
    const int shifts[8] = {1, -1, 8, -8, 9, -9, 7, -7};
    const std::uint64_t masks[8] = {notAFile, notHFile, 0xffffffffffffffffULL, 0xffffffffffffffffULL,
                                    notAFile, notHFile, notHFile, notAFile};

    for(int dir=0; dir<8; dir++) {
        std::uint64_t maskDir = masks[dir];
        std::int64_t shift = shifts[dir];

        std::uint64_t t = 0;
        std::uint64_t p = 0;

        std::uint64_t cur;
        if(shift > 0) cur = (moveMask << shift) & opponent & maskDir;
        else          cur = (moveMask >> (-shift)) & opponent & maskDir;

        while(cur) {
            p |= cur;
            if(shift > 0) cur = (cur << shift) & opponent & maskDir;
            else          cur = (cur >> (-shift)) & opponent & maskDir;
        }
        std::uint64_t end;
        if(shift > 0) end = (p << shift) & player & maskDir;
        else          end = (p >> (-shift)) & player & maskDir;

        if(end) flips |= p;
    }
    if(isBlack) {
        board.black |= flips | moveMask;
        board.white &= ~flips;
    } else {
        board.white |= flips | moveMask;
        board.black &= ~flips;
    }
}