export const STATUS = {
    HIDDEN: "hidden",
    MINE: "mine",
    NUMBER: "number",
    MARKED: "marked",
}

export function createBoard(boardSize, mines) {
    let board = []
    const positions = getMines(boardSize, mines);
    for (let x = 0; x < boardSize; x++) {
        let row = [];
        for (let y = 0; y < boardSize; y++) {
            const element = document.createElement("div");
            let tile = {
                x,
                y,
                element,
                mine: positions.some(p => (p.x == x && p.y == y)),
                get status() {
                    return this.element.dataset.status;
                },
                set status(x) {
                    this.element.dataset.status = x;
                }
            }
            tile.status = STATUS.HIDDEN;

            row.push(tile);
        }
        board.push(row);
    }
    return board;
}

function getMines(size, mines) {
    let positions = [];

    while (positions.length < mines) {
        const pos = {
            x: randint(0, size),
            y: randint(0, size),
        }

        if (positions.some(p => (p.x == pos.x && p.y == pos.y))) continue;
        positions.push(pos);
    }

    return positions;
}



function positionMatch(a, b) {
    return a.x = b.x && a.y == b.y;
}

function randint(a, b) {
    return Math.floor(Math.random() * (b - a) + a);
}

export function markTile(tile) {
    if (tile.status !== STATUS.HIDDEN && tile.status !== STATUS.MARKED) return;
    if (tile.status == STATUS.HIDDEN) tile.status = STATUS.MARKED; else tile.status = STATUS.HIDDEN;
}

function nearbyTiles(tile, board) {
    const tiles = []
    for (let x = -1; x <= 1; x++) {
        for (let y = -1; y <= 1; y++) {
            const ctile = board[tile.x + x]?.[tile.y + y];
            if (ctile)
                tiles.push(ctile)
        }
    }
    return tiles
}

export function revealTile(tile, board) {
    if (tile.status != STATUS.HIDDEN) return;
    if (tile.mine) {
        tile.status = STATUS.MINE; return;
    }
    tile.status = STATUS.NUMBER;
    let nearby = nearbyTiles(tile, board);
    const mines = nearby.filter(t => t.mine);
    if (mines.length == 0)
        nearby.forEach((t) => revealTile(t, board))
    else { tile.element.innerText = mines.length; tile.status += " " + mines.length.toString() }
}

export function checkLose(board) {
    const revealed = board.reduce((count, row) => {
        return count + row.filter(tile => { return (tile.status == STATUS.MINE) }).length
    }, 0);

    if (revealed != 0) {
        board.forEach((row) => row.forEach((cell) => { if (cell.mine) revealTile(cell, board) }));
        return true;
    }
    return false
}

export function checkWin(board, mines) {
    return board.reduce((count, row) => {
        return count + row.filter(tile => { return (tile.status == STATUS.MARKED) }).length
    }, 0) == mines;
}