import { assert } from "../../../core/assert.js";

export class MarkerProcessingRule {

    /**
     * @type {MarkerNodeMatcher}
     */
    matcher = null;


    /**
     *
     * @type {MarkerNodeTransformer[]}
     */
    transformers = [];

    /**
     *
     * @type {MarkerNodeAction}
     */
    action = null;

    /**
     * If this rule is applied, no other rules may be applied to the same node
     * @type {boolean}
     */
    consume = true;

    /**
     *
     * @param {MarkerNodeMatcher} matcher
     * @param {MarkerNodeTransformer[]} [transformers]
     * @param {MarkerNodeAction} action
     * @param {boolean} [consume]
     * @returns {MarkerProcessingRule}
     */
    static from({
                    matcher,
                    transformers = [],
                    action,
                    consume = true
                }) {

        assert.equal(matcher.isMarkerNodeMatcher, true, 'matcher.isMarkerNodeMatcher !== true');
        assert.equal(action.isMarkerNodeAction, true, 'action.isMarkerNodeAction !== true');

        assert.isBoolean(consume, 'consume');


        const r = new MarkerProcessingRule();

        r.matcher = matcher;
        r.transformers = transformers;
        r.action = action;
        r.consume = consume;

        return r;
    }

    /**
     *
     * @param {GridData} grid
     * @param {EntityComponentDataset} ecd
     * @param {number} seed
     */
    initialize(grid, ecd, seed) {
        assert.equal(grid.isGridData, true, 'grid.isGridData !== true');

        assert.defined(ecd, 'ecd');
        assert.notNull(ecd, 'ecd');
        assert.equal(ecd.isEntityComponentDataset, true, 'ecd.isEntityComponentDataset !== true');

        assert.isNumber(seed, 'seed');

        const transformers = this.transformers;
        const nT = transformers.length;

        for (let i = 0; i < nT; i++) {
            const transformer = transformers[i];
            transformer.initialize(grid, seed);
        }

        this.action.initialize(grid, ecd, seed);
    }
}
