import { ConfigType } from '../config.js';
import GridData from '../grid.js';
import { array } from '../dataHelper.js';
import { Color, State } from '../primitives.js';
import Symbol from './symbol.js';
class LetterSymbol extends Symbol {
    /**
     * **Letters must be sorted into one type per area**
     *
     * @param x - The x-coordinate of the symbol.
     * @param y - The y-coordinate of the symbol.
     * @param letter - The letter of the symbol.
     */
    constructor(x, y, letter) {
        super(x, y);
        Object.defineProperty(this, "x", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: x
        });
        Object.defineProperty(this, "y", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: y
        });
        Object.defineProperty(this, "letter", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: letter
        });
        this.letter = letter;
    }
    get id() {
        return `letter`;
    }
    get explanation() {
        return '*Letters* must be sorted into one type per area';
    }
    get configs() {
        return LetterSymbol.CONFIGS;
    }
    createExampleGrid() {
        return LetterSymbol.EXAMPLE_GRID;
    }
    validateSymbol(grid) {
        const thisX = Math.floor(this.x);
        const thisY = Math.floor(this.y);
        let complete = true;
        const visited = array(grid.width, grid.height, () => false);
        const connected = array(grid.width, grid.height, () => false);
        const color = grid.getTile(thisX, thisY).color;
        if (color !== Color.Gray) {
            grid.iterateArea({ x: thisX, y: thisY }, tile => tile.color === Color.Gray || tile.color === color, (tile, x, y) => {
                visited[y][x] = true;
                if (tile.color === Color.Gray)
                    complete = false;
            });
            grid.iterateArea({ x: thisX, y: thisY }, tile => tile.color === color, (_, x, y) => {
                connected[y][x] = true;
            });
        }
        else {
            complete = false;
        }
        for (const symbol of grid.symbols.get(this.id) ?? []) {
            if (symbol !== this && symbol instanceof LetterSymbol) {
                const symbolX = Math.floor(symbol.x);
                const symbolY = Math.floor(symbol.y);
                if (symbol.letter === this.letter) {
                    const theirColor = grid.getTile(symbolX, symbolY).color;
                    if ((color !== Color.Gray && !visited[symbolY][symbolX]) ||
                        (color !== Color.Gray &&
                            theirColor !== Color.Gray &&
                            theirColor !== color)) {
                        return State.Error;
                    }
                }
                else if (color !== Color.Gray && connected[symbolY][symbolX]) {
                    return State.Error;
                }
            }
        }
        return complete ? State.Satisfied : State.Incomplete;
    }
    copyWith({ x, y, letter, }) {
        return new LetterSymbol(x ?? this.x, y ?? this.y, letter ?? this.letter);
    }
    withLetter(letter) {
        return this.copyWith({ letter });
    }
}
Object.defineProperty(LetterSymbol, "CONFIGS", {
    enumerable: true,
    configurable: true,
    writable: true,
    value: Object.freeze([
        {
            type: ConfigType.Number,
            default: 0,
            field: 'x',
            description: 'X',
            configurable: false,
        },
        {
            type: ConfigType.Number,
            default: 0,
            field: 'y',
            description: 'Y',
            configurable: false,
        },
        {
            type: ConfigType.String,
            default: 'A',
            field: 'letter',
            description: 'Letter',
            configurable: true,
        },
    ])
});
Object.defineProperty(LetterSymbol, "EXAMPLE_GRID", {
    enumerable: true,
    configurable: true,
    writable: true,
    value: Object.freeze(GridData.create(['bbbww', 'wwbbw', 'wwbbb', 'bwwww'])
        .addSymbol(new LetterSymbol(0, 0, 'B'))
        .addSymbol(new LetterSymbol(3, 0, 'A'))
        .addSymbol(new LetterSymbol(4, 1, 'A'))
        .addSymbol(new LetterSymbol(3, 2, 'B'))
        .addSymbol(new LetterSymbol(1, 1, 'C'))
        .addSymbol(new LetterSymbol(0, 2, 'C'))
        .addSymbol(new LetterSymbol(4, 3, 'C')))
});
export default LetterSymbol;
export const instance = new LetterSymbol(0, 0, 'A');
