import { AbstractMaterialTransformer } from "../AbstractMaterialTransformer.js";
import { Cache } from "../../../../../core/cache/Cache.js";
import { computeTextureHash } from "../../../../asset/loaders/material/computeTextureHash.js";
import { computeTextureEquality } from "../../../../asset/loaders/material/computeTextureEquality.js";
import {
    TextureAttachmentsByMaterialType
} from "../../../../asset/loaders/material/TextureAttachmensByMaterialType.js";

export class CoalesceTextures extends AbstractMaterialTransformer {
    constructor() {
        super();


        /**
         *
         * @type {Cache<Texture, Texture>}
         */
        this.textureCache = new Cache({
            maxWeight: 1000,
            keyHashFunction: computeTextureHash,
            keyEqualityFunction: computeTextureEquality
        });
    }

    transform(material) {
        const textureCache = this.textureCache;

        //patch textures
        const materialType = material.type;

        /**
         *
         * @type {TextureAttachment[]}
         */
        const attachments = TextureAttachmentsByMaterialType[materialType];

        if (attachments !== undefined) {
            const attachment_count = attachments.length;

            for (let i = 0; i < attachment_count; i++) {
                const attachment = attachments[i];

                const texture = attachment.read(material);

                if (texture === null || texture === undefined) {
                    continue;
                }

                //check cache
                const existingTexture = textureCache.get(texture);

                if (existingTexture !== null) {

                    //console.log('Re-using texture', existingTexture);

                    attachment.write(material, existingTexture);

                } else {

                    //texture was not in cache, cache it
                    textureCache.put(texture, texture);

                }

            }
        }

        return material;
    }
}
