import { assert } from "../../../core/assert.js";
import { Sampler2D } from "../../../engine/graphics/texture/sampler/Sampler2D.js";
import { CellFilterUnaryOperation } from "../core/CellFilterUnaryOperation.js";

export class CellFilterCache extends CellFilterUnaryOperation {

    /**
     *
     * @type {Sampler2D}
     * @private
     */
    __cache = Sampler2D.float32(1, 1, 1);

    /**
     *
     * @type {number}
     */
    scale = 1;

    /**
     *
     * @param {CellFilter} source
     * @param {number} [scale]
     * @returns {CellFilterCache}
     */
    static from(source, scale = 1) {
        assert.equal(source.isCellFilter, true, 'source.isCellFilter !== true');

        const r = new CellFilterCache();

        r.source = source;
        r.scale = scale;

        return r;
    }

    initialize(grid, seed) {
        super.initialize(grid, seed);

        const g_w = grid.width;
        const g_h = grid.height;

        const target_w = this.scale * g_w;
        const target_h = this.scale * g_h;

        const source = this.source;
        const cache = this.__cache;

        cache.resize(target_w, target_h);

        const scale_1 = 1 / this.scale;

        // console.time('Cache filter build');

        let x = 0;
        let y = 0;

        for (y = 0; y < target_h; y++) {
            const grid_y = y * scale_1;

            for (x = 0; x < target_w; x++) {
                const grid_x = x * scale_1;

                const sampleValue = source.execute(grid, grid_x, grid_y, 0);

                cache.writeChannel(x, y, 0, sampleValue);
            }
        }

        // console.timeEnd('Cache filter build');
    }

    execute(grid, x, y, rotation) {
        return this.__cache.sampleChannelBilinear(x, y, 0);
    }
}
