import { magnitude_prefix_index, MAGNITUDE_PREFIXES, MAGNITUDE_SCALES } from "./magnitude_prefix.js";
import { unit_matrix_to_string } from "./unit_matrix_to_string.js";

/**
 * Trim trailing zeros (and a trailing decimal point) from a number string produced by
 * {@link Number.prototype.toFixed}, so that `1.300` becomes `1.3` and `7.000` becomes `7`.
 *
 * @param {string} s
 * @returns {string}
 */
function trim_trailing_zeros(s) {
    if (s.indexOf('.') === -1) {
        return s;
    }

    let end = s.length;

    while (end > 0 && s.charCodeAt(end - 1) === 48 /* '0' */) {
        end--;
    }

    if (end > 0 && s.charCodeAt(end - 1) === 46 /* '.' */) {
        end--;
    }

    return s.substring(0, end);
}

/**
 * Format a numeric value paired with a {@link UnitMatrix} into a compact human-readable string
 * such as `1.3 km/s`, `2.5 N`, or `7 m`.
 *
 * The SI prefix (k, M, m, µ, ...) that brings the magnitude of `value` closest to `[1, 1000)` is
 * selected, then prepended to the unit string. Trailing zeros in the numeric portion are removed.
 *
 * Edge cases:
 *  - dimensionless matrices output just the numeric portion plus a prefix (`1.5k`)
 *  - `0` and non-finite values are reported as-is, with no prefix
 *  - the unit and the value are separated by a single space when a unit symbol is present
 *
 * Optional named-unit recognition: when `named_units` is provided, the unit portion is rendered
 * via {@link unit_matrix_to_string} using that registry — so e.g. `1300 V` can be produced
 * directly instead of `1.3 kkg·m^2/s^3·A`.
 *
 * @param {number} value Numeric magnitude in the unit's base form (e.g. 1300 for 1300 m/s).
 * @param {UnitMatrix} unit_matrix
 * @param {number} [precision=3] Maximum number of digits after the decimal point.
 * @param {NamedUnit[]} [named_units] Optional registry of compound-unit symbols.
 * @param {NamedUnit[]} [dimension_units] Optional override for the per-dimension {@link NamedUnit} mapping; defaults to {@link UNIT_DIMENSION_MAPPING}.
 * @returns {string}
 */
export function format_quantity(
    value,
    unit_matrix,
    precision = 3,
    named_units = undefined,
    dimension_units = undefined
) {
    const unit_string = unit_matrix_to_string(unit_matrix, named_units, dimension_units);

    const index = magnitude_prefix_index(value);
    const prefix = MAGNITUDE_PREFIXES[index];
    const scale = MAGNITUDE_SCALES[index];

    const scaled = value / scale;
    const number_string = trim_trailing_zeros(scaled.toFixed(precision));

    if (unit_string === '') {
        // Dimensionless: number and prefix only ("1.5k", "0").
        return number_string + prefix;
    }

    return number_string + ' ' + prefix + unit_string;
}
