"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSegmentsVisibilities = exports.isOuterAreaIsBlank = exports.isHighResolutionSkinPackTexture = exports.getSkinTargetFromName = exports.getSkinTargetByUniquePixelLocations = exports.isRegionVisible = void 0;
const Database_1 = require("../Database");
const Skin_1 = require("../skins/Skin");
const TextureDefinition_1 = require("../TextureDefinition");
const ModelSegments_1 = require("./ModelSegments");
// Generally, steve == custom and alex == customSlim
const CustomSlimGeometryTags = new Set(["a", "alex", "slim", "customslim"]);
const CustomGeometryTags = new Set(["s", "steve", "custom"]);
class TextureUtilities {
    static _custom = {
        name: "custom",
        allowedTextures: undefined,
        allowedTexturesHighRes: undefined,
        geometryName: "geometry.humanoid.custom",
        segments: [ModelSegments_1.Head, ModelSegments_1.RightArmCustom, ModelSegments_1.LeftArmCustom, ModelSegments_1.LeftLeg, ModelSegments_1.RightLeg],
    };
    static _customSlim = {
        name: "customSlim",
        allowedTextures: undefined,
        allowedTexturesHighRes: undefined,
        geometryName: "geometry.humanoid.customSlim",
        segments: [ModelSegments_1.Head, ModelSegments_1.RightArmSlim, ModelSegments_1.LeftArmSlim, ModelSegments_1.LeftLeg, ModelSegments_1.RightLeg],
    };
    static _isLoaded = false;
    static getBySize(size) {
        switch (size) {
            case Skin_1.SkinModelTarget.Custom:
                return this._custom;
            case Skin_1.SkinModelTarget.CustomSlim:
                return this._customSlim;
            default:
                throw new Error(`Unknown skin size: ${size}`);
        }
    }
    static async getTextureDefinititionForContent(filePath) {
        const contentFile = await Database_1.default.getContentFolderFile(filePath);
        if (!contentFile) {
            return undefined;
        }
        if (!contentFile.isContentLoaded) {
            await contentFile.loadContent();
        }
        if (!(contentFile.content instanceof Uint8Array)) {
            return undefined;
        }
        let textDef = await TextureDefinition_1.default.ensureOnFile(contentFile);
        if (!textDef) {
            return undefined;
        }
        if (!textDef.isContentProcessed) {
            await textDef.processContent();
        }
        return textDef;
    }
    static async load() {
        if (this._isLoaded) {
            return;
        }
        this._custom.allowedTextures = await TextureUtilities.getTextureDefinititionForContent("textures/Custom_AllowedPixels_64.png");
        this._custom.allowedTexturesHighRes = await TextureUtilities.getTextureDefinititionForContent("textures/Custom_AllowedPixels_128.png");
        this._customSlim.allowedTextures = await TextureUtilities.getTextureDefinititionForContent("textures/CustomSlim_AllowedPixels_64.png");
        this._customSlim.allowedTexturesHighRes = await TextureUtilities.getTextureDefinititionForContent("textures/CustomSlim_AllowedPixels_128.png");
        this._isLoaded = true;
    }
}
exports.default = TextureUtilities;
function isRegionVisible(texture, area) {
    const multiplier = isHighResolutionSkinPackTexture(texture) ? 2 : 1;
    const maxX = Math.floor(area.x2) * multiplier;
    const maxY = Math.floor(area.y2) * multiplier;
    if (texture.imageData) {
        for (let x = area.x1 * multiplier; x <= maxX; x++) {
            for (let y = area.y1 * multiplier; y <= maxY; y++) {
                if (texture.getPixel(x, y).a !== 0) {
                    return true;
                }
            }
        }
    }
    return false;
}
exports.isRegionVisible = isRegionVisible;
function getSkinTargetByUniquePixelLocations(texture) {
    const hasCustomSkinPixels = isRegionVisible(texture, ModelSegments_1.RightArmCustomDifference) || isRegionVisible(texture, ModelSegments_1.LeftArmCustomDifference);
    return hasCustomSkinPixels ? Skin_1.SkinModelTarget.Custom : Skin_1.SkinModelTarget.CustomSlim;
}
exports.getSkinTargetByUniquePixelLocations = getSkinTargetByUniquePixelLocations;
function getSkinTargetFromName(textureName) {
    const tokens = textureName.split(/[._]/);
    if (tokens.length > 2) {
        const prefix = tokens[0]?.toLowerCase();
        const suffix = tokens[tokens.length - 2]?.toLowerCase();
        if (CustomGeometryTags.has(prefix) || CustomGeometryTags.has(suffix)) {
            return Skin_1.SkinModelTarget.Custom;
        }
        if (CustomSlimGeometryTags.has(prefix) || CustomSlimGeometryTags.has(suffix)) {
            return Skin_1.SkinModelTarget.CustomSlim;
        }
    }
    return undefined;
}
exports.getSkinTargetFromName = getSkinTargetFromName;
function isHighResolutionSkinPackTexture(textureDefinition) {
    return textureDefinition.width === 128;
}
exports.isHighResolutionSkinPackTexture = isHighResolutionSkinPackTexture;
async function isOuterAreaIsBlank(texture, size) {
    await TextureUtilities.load();
    if (texture.width === undefined || texture.height === undefined) {
        throw new Error("Texture width or height is undefined");
    }
    const allowedAlphaMask = isHighResolutionSkinPackTexture(texture)
        ? TextureUtilities.getBySize(size).allowedTexturesHighRes
        : TextureUtilities.getBySize(size).allowedTextures;
    if (!allowedAlphaMask) {
        throw new Error("Could not find reference for texture");
    }
    if (texture.imageData) {
        for (let x = 0; x < texture.width; ++x) {
            for (let y = 0; y < texture.height; ++y) {
                const texIsVisibleInDisallowedSpot = allowedAlphaMask.getPixel(x, y).a === 0 && texture.getPixel(x, y).a > 0;
                if (texIsVisibleInDisallowedSpot) {
                    return false;
                }
            }
        }
    }
    return true;
}
exports.isOuterAreaIsBlank = isOuterAreaIsBlank;
function getSegmentsVisibilities(texture, size) {
    const values = TextureUtilities.getBySize(size);
    return values.segments.map((segment) => checkTextureVisibilityForSegment(texture, segment));
}
exports.getSegmentsVisibilities = getSegmentsVisibilities;
function checkTextureVisibilityForSegment(texture, segment) {
    return {
        segmentName: segment.name,
        visibilities: {
            top: isRegionVisible(texture, segment.parts.top),
            front: isRegionVisible(texture, segment.parts.front),
            left: isRegionVisible(texture, segment.parts.left),
            right: isRegionVisible(texture, segment.parts.right),
            bottom: isRegionVisible(texture, segment.parts.bottom),
            back: isRegionVisible(texture, segment.parts.back),
        },
    };
}

//# sourceMappingURL=../../maps/minecraft/textures/TextureUtilities.js.map
