import { Action } from "../../../src/core/process/undo/Action.js";
import { Sampler2D } from "../../../src/engine/graphics/texture/sampler/Sampler2D.js";
import {
    sampler2d_sub_copy_same_item_size
} from "../../../src/engine/graphics/texture/sampler/sampler2d_sub_copy_same_item_size.js";

export class ModifyPatchSampler2DAction extends Action {
    /**
     *
     * @param {Sampler2D} sampler
     * @param {number[]} bounds
     */
    constructor(sampler, bounds) {
        super();

        /**
         *
         * @type {Sampler2D}
         * @private
         */
        this.__sampler = sampler;

        /**
         *
         * @type {number[]}
         * @private
         */
        this.__bounds = bounds;

        const width = this.__bounds[2] - this.__bounds[0];
        const height = this.__bounds[3] - this.__bounds[1];

        /**
         *
         * @type {Sampler2D}
         */
        this.__patch_new = Sampler2D.float32(sampler.itemSize, width, height);

        /**
         *
         * @type {Sampler2D}
         * @private
         */
        this.__patch_old = Sampler2D.float32(sampler.itemSize, width, height);
    }

    get patch() {
        return this.__patch_new;
    }

    get x() {
        return this.__bounds[0];
    }

    get y() {
        return this.__bounds[1];
    }

    /**
     *
     * @param {number} x coordinate in global space
     * @param {number} y coordinate in global space
     * @param {number} [channel]
     * @returns {number} delta between original value and the new one after the change
     */
    computeDelta(x, y, channel = 0) {
        const _x = x - this.x;

        if (_x < 0 || _x > this.__patch_new.width - 1) {
            return 0;
        }

        const _y = y - this.y;

        if (_y < 0 || _y > this.__patch_new.height - 1) {
            return 0;
        }

        const value_old = this.__patch_old.sampleChannelBilinear(_x, _y, channel);
        const value_new = this.__patch_new.sampleChannelBilinear(_x, _y, channel);

        return value_new - value_old;
    }

    computeByteSize() {
        return this.__patch_new.computeByteSize() + this.__patch_old.computeByteSize() + 280;
    }


    async apply(context) {

        /**
         *
         * @type {Sampler2D}
         */
        const source = this.__sampler;

        //store old data from the patch
        const patch_old = this.__patch_old;

        sampler2d_sub_copy_same_item_size(patch_old,source, this.x, this.y, 0, 0, patch_old.width, patch_old.height);

        const patch_new = this.__patch_new;

        //apply the patch
        sampler2d_sub_copy_same_item_size(source,patch_new, 0, 0, this.x, this.y, patch_new.width, patch_new.height);
    }

    async revert(context) {
        /**
         *
         * @type {Sampler2D}
         */
        const source = this.__sampler;

        const patch_old = this.__patch_old;

        //apply the patch
        sampler2d_sub_copy_same_item_size(source,patch_old, 0, 0, this.x, this.y, patch_old.width, patch_old.height);
    }
}
