import { AbstractLight } from "./AbstractLight.js";
import { aabb3_matrix4_project_by_corners } from "../../../../../core/geom/3d/aabb/aabb3_matrix4_project_by_corners.js";
import { aabb3_build_corners } from "../../../../../core/geom/3d/aabb/aabb3_build_corners.js";
import { array_copy } from "../../../../../core/collection/array/array_copy.js";
import { mat4 } from "gl-matrix";
import Signal from "../../../../../core/events/signal/Signal.js";

const corners = [];

export class Decal extends AbstractLight {
    constructor() {
        super();

        /**
         * Transform matrix, initial volume is a unit cube
         * @type {number[]|Float32Array|mat4[]}
         */
        this.transform = new Float32Array(16);
        this.transform_inverse = new Float32Array(16);
        this.uv = new Float32Array(4);

        this.color = new Float32Array(4);
        // initialize color to full white
        this.color.fill(1);


        /**
         *
         * @type {Sampler2D}
         */
        this.texture_diffuse = null;

        /**
         * Order in which decal should be applied, higher priority decals will be drawn first
         * NOTE: not implemented yet
         * @type {number}
         */
        this.draw_priority = 0;

        this.__signal_transfom_changed = new Signal();
    }

    /**
     *
     * @param {number[]|Float32Array|ArrayLike<number>} m
     */
    setTransform(m) {
        mat4.copy(this.transform, m);
        mat4.invert(this.transform_inverse, this.transform);

        this.__signal_transfom_changed.send0();
    }

    handleUvPositionChange(x, y) {
        this.uv[0] = x;
        this.uv[1] = y;
    }

    handleUvSizeChange(x, y) {
        this.uv[2] = x;
        this.uv[3] = y;
    }

    compare(other) {
        if (other.isDecal) {
            const dDraw = this.draw_priority - other.draw_priority;

            if (dDraw !== 0) {
                return dDraw;
            }
        }

        return super.compare(other);
    }

    onDimensionChanged(f, thisArg) {

        this.__signal_transfom_changed.add(f, thisArg);
    }

    offDimensionChanged(f, thisArg) {

        this.__signal_transfom_changed.remove(f, thisArg);
    }

    getCenter(result) {
        // extract translation portion of the matrix
        result[0] = this.transform[12];
        result[1] = this.transform[13];
        result[2] = this.transform[14];
    }

    getAABB(result) {
        aabb3_build_corners(corners, 0, -0.5, -0.5, -0.5, 0.5, 0.5, 0.5);

        aabb3_matrix4_project_by_corners(result, corners, this.transform);
    }

    toArray(destination, address) {
        array_copy(this.transform_inverse, 0, destination, address, 16);
        // array_copy(this.transform , 0, destination, address, 16);

        array_copy(this.uv, 0, destination, address + 16, 4);

        // required for sorting
        // destination[address + 20] = this.draw_priority;
        // destination[address + 21] = this.id;

        // color
        array_copy(this.color, 0, destination, address + 20, 4);

        return 24;
    }
}

/**
 * @readonly
 * @type {boolean}
 */
Decal.prototype.isDecal = true;

Decal.prototype.ENCODED_SLOT_COUNT = 24;
