import { scs3d_sample_linear } from "./scs3d_sample_linear.js";

export class SingleChannelSampler3D {

    data = new Float32Array(0)
    #resolution = new Uint32Array([0, 0, 0])

    /**
     *
     * @param {Float32Array} data
     * @param {ArrayLike<number>|Uint32Array|number[]} resolution
     * @return {SingleChannelSampler3D}
     */
    static from(data, resolution) {
        const r = new SingleChannelSampler3D();

        r.data = data;
        r.#resolution.set(resolution);

        return r;
    }

    set resolution(v) {
        const width = v[0];
        const height = v[1];
        const depth = v[2];

        const old_width = this.#resolution[0];
        const old_height = this.#resolution[1];
        const old_depth = this.#resolution[2];

        if (old_width === width && old_height === height && old_depth === depth) {
            // no change
            return;
        }

        this.#resolution[0] = width;
        this.#resolution[1] = height;
        this.#resolution[2] = depth

        const new_data_size = width * height * depth;

        if (new_data_size !== old_width * old_height * old_depth) {

            this.data = new Float32Array(new_data_size);

        }
    }

    get resolution() {
        return this.#resolution;
    }

    /**
     *
     * @param {number} x
     * @param {number} y
     * @param {number} z
     * @param {number} value
     */
    write(x, y, z, value) {
        const resolution = this.#resolution;

        const res_x = resolution[0];
        const res_y = resolution[1];

        this.data[z * res_y * res_x + y * res_x + x] = value;
    }

    /**
     *
     * @param {number} x
     * @param {number} y
     * @param {number} z
     * @returns {number}
     */
    sample_channel_linear(x, y, z) {
        const resolution = this.#resolution;

        const res_x = resolution[0];
        const res_y = resolution[1];
        const res_z = resolution[2];
        return scs3d_sample_linear(this.data, res_x, res_y, res_z, x, y, z);
    }

    /**
     *
     * @param {SingleChannelSampler3D} other
     */
    copy(other) {
        this.resolution = other.#resolution;

        this.data.set(other.data);
    }

    clone() {
        const r = new SingleChannelSampler3D();

        r.copy(this);

        return r;
    }
}
