"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PART_FACE_TRANSFORMS = exports.LEFT_ARM_FACE_MAP = exports.RIGHT_ARM_FACE_MAP = exports.IDENTITY_FACE_MAP = void 0;
exports.mirrorArmFaceTransform = mirrorArmFaceTransform;
exports.getFaceDimensions = getFaceDimensions;
exports.extractSourceFacePixels = extractSourceFacePixels;
exports.transformFacePixels = transformFacePixels;
exports.IDENTITY_FACE_MAP = {
    up: { source: 'up', rotate: 0 },
    down: { source: 'down', rotate: 0 },
    north: { source: 'north', rotate: 0 },
    south: { source: 'south', rotate: 0 },
    east: { source: 'east', rotate: 0 },
    west: { source: 'west', rotate: 0 },
};
exports.RIGHT_ARM_FACE_MAP = {
    up: { source: 'east', rotate: 90 },
    down: { source: 'west', rotate: 90 },
    north: { source: 'north', rotate: 90 },
    south: { source: 'south', rotate: 270 },
    east: { source: 'up', rotate: 90 },
    west: { source: 'down', rotate: 90 },
};
function mirrorArmFaceTransform(transform) {
    const rotate = ((360 - (transform.rotate ?? 0)) % 360);
    return {
        source: transform.source,
        rotate,
        flipHorizontal: transform.flipHorizontal ?? false,
        flipVertical: transform.flipVertical ?? false,
    };
}
exports.LEFT_ARM_FACE_MAP = {
    up: mirrorArmFaceTransform(exports.RIGHT_ARM_FACE_MAP.up),
    down: mirrorArmFaceTransform(exports.RIGHT_ARM_FACE_MAP.down),
    north: mirrorArmFaceTransform(exports.RIGHT_ARM_FACE_MAP.north),
    south: mirrorArmFaceTransform(exports.RIGHT_ARM_FACE_MAP.south),
    east: { ...mirrorArmFaceTransform(exports.RIGHT_ARM_FACE_MAP.west), flipHorizontal: true },
    west: { ...mirrorArmFaceTransform(exports.RIGHT_ARM_FACE_MAP.east), flipHorizontal: true },
};
exports.PART_FACE_TRANSFORMS = {
    torso: exports.IDENTITY_FACE_MAP,
    head: exports.IDENTITY_FACE_MAP,
    leg_left: exports.IDENTITY_FACE_MAP,
    leg_right: exports.IDENTITY_FACE_MAP,
    arm_right: exports.RIGHT_ARM_FACE_MAP,
    arm_left: exports.LEFT_ARM_FACE_MAP,
};
function getFaceDimensions(size, face) {
    const [sxRaw, syRaw, szRaw] = size;
    const sx = Math.max(1, Math.round(Math.abs(sxRaw)));
    const sy = Math.max(1, Math.round(Math.abs(syRaw)));
    const sz = Math.max(1, Math.round(Math.abs(szRaw)));
    switch (face) {
        case 'up':
        case 'down':
            return [sx, sz];
        case 'north':
        case 'south':
            return [sx, sy];
        case 'east':
        case 'west':
            return [sz, sy];
        default:
            return [sx, sy];
    }
}
const clamp = (value, min, max) => {
    if (!Number.isFinite(value)) {
        return min;
    }
    if (value < min) {
        return min;
    }
    if (value > max) {
        return max;
    }
    return value;
};
const rotatePixels = (data, width, height, rotation) => {
    if (rotation === 0) {
        return { data, width, height };
    }
    const rotate = ((rotation % 360) + 360) % 360;
    const newWidth = rotate === 90 || rotate === 270 ? height : width;
    const newHeight = rotate === 90 || rotate === 270 ? width : height;
    const result = new Uint8Array(data.length);
    for (let y = 0; y < height; y += 1) {
        for (let x = 0; x < width; x += 1) {
            const srcIndex = (y * width + x) * 4;
            let destX = 0;
            let destY = 0;
            switch (rotate) {
                case 0:
                    destX = x;
                    destY = y;
                    break;
                case 90:
                    destX = height - 1 - y;
                    destY = x;
                    break;
                case 180:
                    destX = width - 1 - x;
                    destY = height - 1 - y;
                    break;
                case 270:
                    destX = y;
                    destY = width - 1 - x;
                    break;
            }
            const destIndex = (destY * newWidth + destX) * 4;
            result[destIndex] = data[srcIndex];
            result[destIndex + 1] = data[srcIndex + 1];
            result[destIndex + 2] = data[srcIndex + 2];
            result[destIndex + 3] = data[srcIndex + 3];
        }
    }
    return { data: result, width: newWidth, height: newHeight };
};
const flipPixels = (data, width, height, flipHorizontal, flipVertical) => {
    if (!flipHorizontal && !flipVertical) {
        return data;
    }
    const result = new Uint8Array(data.length);
    for (let y = 0; y < height; y += 1) {
        for (let x = 0; x < width; x += 1) {
            const srcIndex = (y * width + x) * 4;
            const targetX = flipHorizontal ? width - 1 - x : x;
            const targetY = flipVertical ? height - 1 - y : y;
            const destIndex = (targetY * width + targetX) * 4;
            result[destIndex] = data[srcIndex];
            result[destIndex + 1] = data[srcIndex + 1];
            result[destIndex + 2] = data[srcIndex + 2];
            result[destIndex + 3] = data[srcIndex + 3];
        }
    }
    return result;
};
function extractSourceFacePixels(cubeInfo, face, textureWidth, textureHeight, texturePixels) {
    const rect = cubeInfo.faces[face];
    const width = Math.max(1, Math.floor(rect.width));
    const height = Math.max(1, Math.floor(rect.height));
    const data = new Uint8Array(width * height * 4);
    for (let row = 0; row < height; row += 1) {
        for (let col = 0; col < width; col += 1) {
            const srcX = clamp(Math.floor(rect.x + col), 0, textureWidth - 1);
            const srcY = clamp(Math.floor(rect.y + row), 0, textureHeight - 1);
            const srcIndex = (srcY * textureWidth + srcX) * 4;
            const dstIndex = (row * width + col) * 4;
            data[dstIndex] = texturePixels[srcIndex];
            data[dstIndex + 1] = texturePixels[srcIndex + 1];
            data[dstIndex + 2] = texturePixels[srcIndex + 2];
            data[dstIndex + 3] = texturePixels[srcIndex + 3];
        }
    }
    if (face === 'down') {
        return rotatePixels(data, width, height, 180);
    }
    if (face === 'up') {
        const flipped = flipPixels(data, width, height, true, false);
        return { data: flipped, width, height };
    }
    return { data, width, height };
}
function transformFacePixels(source, transform, textureWidth, textureHeight, texturePixels) {
    const { source: face, rotate = 0, flipHorizontal = false, flipVertical = false } = transform;
    const extracted = extractSourceFacePixels(source, face, textureWidth, textureHeight, texturePixels);
    let data = extracted.data;
    if (flipHorizontal || flipVertical) {
        data = flipPixels(data, extracted.width, extracted.height, flipHorizontal, flipVertical);
    }
    const rotated = rotatePixels(data, extracted.width, extracted.height, rotate);
    return { data: rotated.data, width: rotated.width, height: rotated.height };
}
//# sourceMappingURL=face-map.js.map