import { BufferAttribute } from "three";
import { assert } from "../../../../core/assert.js";

/**
 *
 * @param {THREE.BufferAttribute} attribute
 * @returns {THREE.BufferAttribute} returns denormalized attribute, if input is already denormalized returns input
 */
export function buffer_attribute_denormalize(attribute) {
    assert.notEqual(attribute.isInterleavedBufferAttribute, true, 'attribute must not be interleaved');

    if (!attribute.normalized) {
        // already denormalized
        return attribute;
    }

    const raw_data = attribute.array;
    const input_array_type = raw_data.constructor;

    if (input_array_type === Float32Array) {
        // special case
        return new BufferAttribute(raw_data, attribute.itemSize, false);
    }

    const value_count = attribute.count * attribute.itemSize;
    const denormalized = new Float32Array(value_count);

    // denormalization inlined for speed
    switch (input_array_type) {
        case Uint32Array:
            for (let i = 0; i < value_count; i++) {
                denormalized[i] = raw_data[i] / 0xffffffff;
            }
            break;
        case Uint16Array:
            for (let i = 0; i < value_count; i++) {
                denormalized[i] = raw_data[i] / 0xffff;
            }
            break;
        case Uint8Array:
            for (let i = 0; i < value_count; i++) {
                denormalized[i] = raw_data[i] / 0xff;
            }
            break;
        case Int32Array:
            for (let i = 0; i < value_count; i++) {
                denormalized[i] = Math.max(raw_data[i] / 0x7fffffff, -1);
            }
            break;
        case Int16Array:
            for (let i = 0; i < value_count; i++) {
                denormalized[i] = Math.max(raw_data[i] / 0x7fff, -1);
            }
            break;
        case Int8Array:
            for (let i = 0; i < value_count; i++) {
                denormalized[i] = Math.max(raw_data[i] / 0x7f, -1);
            }
            break;
        default:
            throw new Error(`Unsupported data type ${input_array_type}`);
    }

    return new BufferAttribute(denormalized, attribute.itemSize, false);

}