Source: engine_number.js

/**
 * Structures to represent numbers with units inside the engine.
 *
 * @license BSD, see LICENSE.md.
 */

/**
 * Representation of a number with units within the engine.
 */
class EngineNumber {
  /**
   * Create a new number with units.
   *
   * @param value - The numeric value (float, or int).
   * @param units - The units to associate with this value like kg.
   * @param originalString - Optional original string format to preserve user formatting.
   */
  constructor(value, units, originalString) {
    const self = this;
    self._value = value;
    self._units = units;
    self._originalString = originalString;
  }

  /**
   * Get the value of this number.
   *
   * @returns Value as an integer or float.
   */
  getValue() {
    const self = this;
    return self._value;
  }

  /**
   * Get the units associated with this number.
   *
   * @returns The units as a string like "mt".
   */
  getUnits() {
    const self = this;
    return self._units;
  }

  /**
   * Check if this number has equipment units.
   *
   * @returns {boolean} True if the units represent equipment units.
   */
  hasEquipmentUnits() {
    const self = this;
    return self._units.startsWith("unit");
  }

  /**
   * Get the original string format if available.
   *
   * @returns {string|null} The original string format, or null if not available.
   */
  getOriginalString() {
    const self = this;
    return self._originalString || null;
  }

  /**
   * Check if this number has an original string format preserved.
   *
   * @returns {boolean} True if original string format is available.
   */
  hasOriginalString() {
    const self = this;
    return self._originalString !== undefined && self._originalString !== null;
  }
}

/**
 * Converts a numeric value to an unambiguous US-format string.
 *
 * Ensures numbers are formatted to avoid ambiguity (e.g., 1.234 becomes
 * "1.2340", 1234 becomes "1,234.0"). Used when we need to generate
 * formatted strings but don't have access to the user's original
 * formatting.
 *
 * @param {number} numericValue - The numeric value to format
 * @returns {string} The unambiguous US-format number string
 */
function makeNumberUnambiguousString(numericValue) {
  if (numericValue === null || numericValue === undefined || isNaN(numericValue)) {
    return String(numericValue);
  }

  const absValue = Math.abs(numericValue);
  const isNegative = numericValue < 0;

  // Handle integers (no decimal part)
  if (Number.isInteger(numericValue)) {
    const formatted = absValue.toLocaleString("en-US") + ".0";
    return isNegative ? "-" + formatted : formatted;
  }

  // Handle decimals - ensure at least one trailing zero for disambiguation
  let formatted = absValue.toLocaleString("en-US", {
    minimumFractionDigits: 1,
    maximumFractionDigits: 20,
  });

  // If the number doesn't end with 0, add a trailing 0 for disambiguation
  if (!formatted.endsWith("0")) {
    formatted += "0";
  }

  return isNegative ? "-" + formatted : formatted;
}

export {EngineNumber, makeNumberUnambiguousString};