import { assert } from "../../assert.js";
import { array_copy } from "../../collection/array/array_copy.js";
import { clamp } from "../clamp.js";
import { computeNonuniformCatmullRomSplineSample } from "./computeNonuniformCatmullRomSplineSample.js";

/**
 *
 * @type {number[]}
 */
const sample = [];
/**
 *
 * @type {number[]}
 */
const p0 = [];
/**
 *
 * @type {number[]}
 */
const p1 = [];
/**
 *
 * @type {number[]}
 */
const p2 = [];
/**
 *
 * @type {number[]}
 */
const p3 = [];

/**
 *
 * @param {number[]} result
 * @param {number[]} input
 * @param {number} input_length number of points in the input
 * @param {number} dimensions number of dimensions per vertex
 * @param {number} sample_count number of discrete points to be generated
 * @param {number} [alpha=0.5] parameter for control point weights (see non-parametric catmull-rom for details on "alpha" definition)
 */
export function computeCatmullRomSpline(
    result,
    input, input_length,
    dimensions, sample_count, alpha = 0.5
) {
    assert.greaterThan(dimensions, 0, 'number of dimensions must be greater than 0');
    assert.isNonNegativeInteger(dimensions, 'dimensions');

    assert.greaterThanOrEqual(sample_count, 2, 'number of samples must be >= 2');
    assert.isNonNegativeInteger(sample_count, 'sample_count');

    for (let i = 0; i < sample_count; i++) {
        const t = i / (sample_count - 1);

        const position_absolute = t * (input_length - 1);
        const position_index = Math.floor(position_absolute);
        const position_relative = position_absolute - position_index;

        const i0 = clamp(position_index - 1, 0, input_length - 1);
        const i1 = clamp(position_index, 0, input_length - 1);
        const i2 = clamp(position_index + 1, 0, input_length - 1);
        const i3 = clamp(position_index + 2, 0, input_length - 1);

        // read relevant inputs
        array_copy(input, i0 * dimensions, p0, 0, dimensions);
        array_copy(input, i1 * dimensions, p1, 0, dimensions);
        array_copy(input, i2 * dimensions, p2, 0, dimensions);
        array_copy(input, i3 * dimensions, p3, 0, dimensions);

        computeNonuniformCatmullRomSplineSample(sample, p0, p1, p2, p3, dimensions, position_relative, alpha);

        const result_address = i * dimensions;

        array_copy(sample, 0, result, result_address, dimensions);

    }


}
