import BTModule, { BTTile, IntArray2D, } from '../data.js';
export default class LetterBTModule extends BTModule {
    constructor(instrs, width, height) {
        super();
        Object.defineProperty(this, "letters", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "letterGrid", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        this.letters = [];
        this.letterGrid = IntArray2D.create(width, height);
        const letterMap = new Map();
        let letterCount = 0;
        for (const instr of instrs) {
            if (!letterMap.has(instr.letter)) {
                letterMap.set(instr.letter, letterCount);
                this.letters[letterCount] = [];
                letterCount += 1;
            }
            const id = letterMap.get(instr.letter);
            this.letters[id].push(instr);
            this.letterGrid.set(Math.floor(instr.x), Math.floor(instr.y), id + 1);
        }
    }
    checkGlobal(grid) {
        const visited = IntArray2D.create(grid.width, grid.height);
        for (let id = 0; id < this.letters.length; id++) {
            for (const symbol of this.letters[id]) {
                const symbolX = Math.floor(symbol.x);
                const symbolY = Math.floor(symbol.y);
                if (grid.getTile(symbolX, symbolY) === BTTile.Empty)
                    continue;
                if (!this.visitArea(grid, visited, { x: symbolX, y: symbolY }, id + 1))
                    return false;
                break;
            }
        }
        return { tilesNeedCheck: null, ratings: null };
    }
    visitArea(grid, visited, pos, id) {
        const tile = grid.getTile(pos.x, pos.y);
        const sameTileQueue = [pos];
        const usableTileQueue = [];
        let letterVisited = 0;
        visited.set(pos.x, pos.y, id);
        // Count same tile
        while (sameTileQueue.length > 0) {
            const curPos = sameTileQueue.pop();
            const letterId = this.letterGrid.get(curPos.x, curPos.y);
            if (letterId === id) {
                letterVisited += 1;
            }
            else if (letterId !== 0) {
                return false;
            }
            for (const edge of grid.getEdges(curPos)) {
                if ((visited.get(edge.x, edge.y) & 0b01111111) === id)
                    continue;
                const edgeTile = grid.getTile(edge.x, edge.y);
                if (edgeTile === BTTile.Empty) {
                    usableTileQueue.push(edge);
                    visited.set(edge.x, edge.y, id | 0b10000000);
                }
                else if (edgeTile === tile) {
                    sameTileQueue.push(edge);
                    visited.set(edge.x, edge.y, id);
                }
            }
        }
        if (letterVisited === this.letters[id - 1].length)
            return true;
        // Count usable tile
        while (usableTileQueue.length > 0) {
            const curPos = usableTileQueue.pop();
            const letterId = this.letterGrid.get(curPos.x, curPos.y);
            if (letterId === id) {
                letterVisited += 1;
                if (letterVisited === this.letters[id - 1].length)
                    return true;
            }
            for (const edge of grid.getEdges(curPos)) {
                if ((visited.get(edge.x, edge.y) & 0b01111111) === id)
                    continue;
                const edgeTile = grid.getTile(edge.x, edge.y);
                if (edgeTile === BTTile.Empty || edgeTile === tile) {
                    usableTileQueue.push(edge);
                    visited.set(edge.x, edge.y, id | 0b10000000);
                }
            }
        }
        return letterVisited === this.letters[id - 1].length;
    }
}
