import { DataTexture, NearestFilter, RGBAIntegerFormat, UnsignedShortType } from "three";

export class AtlasLookupTexture {
    constructor() {
        /**
         *
         * @type {TextureAtlas|null}
         */
        this.atlas = null;

        /**
         *
         * @type {number}
         * @private
         */
        this.__row_size = 32;

        /**
         *
         * @type {Uint16Array}
         * @private
         */
        this.__data = new Uint16Array(4);

        this.texture = new DataTexture(this.__data, 1, 1);

        this.texture.format = RGBAIntegerFormat;
        this.texture.type = UnsignedShortType;
        this.texture.magFilter = NearestFilter;
        this.texture.minFilter = NearestFilter;
        this.texture.generateMipmaps = false;
        this.texture.internalFormat = 'RGB16UI';
    }

    /**
     *
     * @param {TextureAtlas} atlas
     */
    attach(atlas) {
        this.atlas = atlas;
    }

    update() {
        const atlas = this.atlas;

        const patches = atlas.patches;

        const patch_count = patches.length;

        const rowSize = this.__row_size;

        const expected_row_count = Math.ceil(patch_count / rowSize);

        const texture = this.texture;

        const image = texture.image;

        if (image.height < expected_row_count) {
            texture.dispose();

            image.height = expected_row_count;
            image.width = rowSize;

            image.data = new Uint16Array(expected_row_count * rowSize * 4);
        }

        const data = image.data;

        for (let i = 0; i < patch_count; i++) {
            const patch = patches[i];

            const address = i * 4;

            const position = patch.position;
            const size = patch.size;

            data[address] = position.x;
            data[address + 1] = position.y;

            data[address + 2] = size.y;
            data[address + 3] = size.y;
        }

        texture.needsUpdate = true;
    }
}
