import { ConfigType } from '../config.js';
import GridData from '../grid.js';
import { Color, State } from '../primitives.js';
import AreaNumberSymbol from '../symbols/areaNumberSymbol.js';
import Rule from './rule.js';
class CellCountRule extends Rule {
    /**
     * **There are &lt;count&gt; &lt;color&gt; cells in total**
     *
     * @param color - The color of the cells to count.
     * @param count - The total number of cells of the given color.
     */
    constructor(color, count) {
        super();
        Object.defineProperty(this, "color", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: color
        });
        Object.defineProperty(this, "count", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: count
        });
        this.color = color;
        this.count = count;
    }
    get id() {
        return `cell_count`;
    }
    get explanation() {
        return `There ${this.count === 1 ? 'is' : 'are'} ${this.count} ${this.color} cell${this.count === 1 ? '' : 's'} *in total*`;
    }
    get configs() {
        return CellCountRule.CONFIGS;
    }
    createExampleGrid() {
        if (this.count < CellCountRule.EXAMPLE_GRID_LIGHT.length) {
            if (this.color === Color.Light) {
                return CellCountRule.EXAMPLE_GRID_LIGHT[this.count];
            }
            else {
                return CellCountRule.EXAMPLE_GRID_DARK[this.count];
            }
        }
        else {
            const grid = this.color === Color.Light
                ? GridData.create(['wbbbb', 'wwbbb', 'wwwbb', 'wwwwb'])
                : GridData.create(['bwwww', 'bbwww', 'bbbww', 'bbbbw']);
            return grid.addSymbol(new AreaNumberSymbol(1, 2, this.count));
        }
    }
    get searchVariants() {
        return CellCountRule.SEARCH_VARIANTS;
    }
    validateGrid(grid) {
        let colored = 0;
        let possible = 0;
        grid.forEach(tile => {
            if (!tile.exists)
                return;
            if (tile.color === this.color)
                colored++;
            if (tile.color === Color.Gray)
                possible++;
        });
        if (colored > this.count || colored + possible < this.count) {
            return { state: State.Error, positions: [] };
        }
        else if (colored === this.count && possible === 0) {
            return { state: State.Satisfied };
        }
        else {
            return { state: State.Incomplete };
        }
    }
    copyWith({ color, count }) {
        return new CellCountRule(color ?? this.color, count ?? this.count);
    }
    withColor(color) {
        return this.copyWith({ color });
    }
    withCount(count) {
        return this.copyWith({ count });
    }
}
Object.defineProperty(CellCountRule, "CONFIGS", {
    enumerable: true,
    configurable: true,
    writable: true,
    value: Object.freeze([
        {
            type: ConfigType.Color,
            default: Color.Light,
            allowGray: false,
            field: 'color',
            description: 'Color',
            configurable: true,
        },
        {
            type: ConfigType.Number,
            default: 10,
            min: 0,
            field: 'count',
            description: 'Count',
            configurable: true,
        },
    ])
});
Object.defineProperty(CellCountRule, "EXAMPLE_GRID_LIGHT", {
    enumerable: true,
    configurable: true,
    writable: true,
    value: Object.freeze([
        GridData.create(['bbbbb', 'bbbbb', 'bbbbb', 'bbbbb']),
        GridData.create(['bbbbb', 'bbbbb', 'bwbbb', 'bbbbb']).withSymbols([
            new AreaNumberSymbol(1, 2, 1),
        ]),
        GridData.create(['bbbbb', 'bbbbb', 'bwwbb', 'bbbbb']).withSymbols([
            new AreaNumberSymbol(1, 2, 2),
        ]),
        GridData.create(['bbbbb', 'bwbbb', 'bwwbb', 'bbbbb']).withSymbols([
            new AreaNumberSymbol(1, 2, 3),
        ]),
        GridData.create(['bbbbb', 'bwwbb', 'bwwbb', 'bbbbb']).withSymbols([
            new AreaNumberSymbol(1, 2, 4),
        ]),
        GridData.create(['bbbbb', 'bwwbb', 'bwwwb', 'bbbbb']).withSymbols([
            new AreaNumberSymbol(1, 2, 5),
        ]),
        GridData.create(['bbbbb', 'bwwwb', 'bwwwb', 'bbbbb']).withSymbols([
            new AreaNumberSymbol(1, 2, 6),
        ]),
        GridData.create(['bbbbb', 'bbbbb', 'wwwbb', 'wwwwb']).withSymbols([
            new AreaNumberSymbol(1, 2, 7),
        ]),
        GridData.create(['bbbbb', 'wbbbb', 'wwwbb', 'wwwwb']).withSymbols([
            new AreaNumberSymbol(1, 2, 8),
        ]),
        GridData.create(['bbbbb', 'wwbbb', 'wwwbb', 'wwwwb']).withSymbols([
            new AreaNumberSymbol(1, 2, 9),
        ]),
        GridData.create(['wbbbb', 'wwbbb', 'wwwbb', 'wwwwb']).withSymbols([
            new AreaNumberSymbol(1, 2, 10),
        ]),
    ])
});
Object.defineProperty(CellCountRule, "EXAMPLE_GRID_DARK", {
    enumerable: true,
    configurable: true,
    writable: true,
    value: Object.freeze(CellCountRule.EXAMPLE_GRID_LIGHT.map(grid => grid.withTiles(tiles => tiles.map(row => row.map(tile => tile.withColor(tile.color === Color.Dark ? Color.Light : Color.Dark))))))
});
Object.defineProperty(CellCountRule, "SEARCH_VARIANTS", {
    enumerable: true,
    configurable: true,
    writable: true,
    value: [
        new CellCountRule(Color.Light, 10).searchVariant(),
        new CellCountRule(Color.Dark, 10).searchVariant(),
    ]
});
export default CellCountRule;
export const instance = new CellCountRule(Color.Dark, 10);
