"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getParameterFormattedUnitDisplay = exports.getFormattedUnitDisplay = exports.getUnitConverterForParameter = exports.unitConverterParameters = exports.unitConverters = exports.convertParameterVelocityAffectedValue = exports.convertParameterFeedConstantAffectedVelocityValue = exports.convertFeedConstantAffectedVelocityValue = exports.convertParameterFeedConstantAffectedPositionValue = exports.convertFeedConstantAffectedPositionValue = exports.convertParameterSiUnitVelocityAffectedValue = exports.convertSiUnitVelocityAffectedValue = exports.parseSiUnitVelocityValue = exports.symbolToSiUnitVelocityValue = exports.siUnitVelocityValueToSymbol = exports.unitConverterAccelerationParameters = exports.unitConverterVelocityParameters = exports.unitConverterPositionParameters = exports.siUnitVelocityAffectedParameters = exports.feedConstantPositionAffectedParameters = exports.feedConstantAndSiUnitVelocityAffectedParameters = void 0;
const util_1 = require("./util");
/**
 * List of parameters affected by Feed constant and SI unit velocity.
 *
 * This is derived from the Google Sheet document titled "Objects scaled with Feed and SI unit velocity".
 */
exports.feedConstantAndSiUnitVelocityAffectedParameters = [
    // Position
    [0x2004, 0x08, 0x00b50000, false, false],
    [0x2005, 0x01, 0x00b50000, true, false],
    [0x2005, 0x04, 0x00b50000, true, false],
    [0x2040, 0x00, 0x00b50000, false, false],
    [0x2110, 0x06, 0x00b50000, false, false],
    [0x2110, 0x19, 0x00b50000, false, false],
    [0x2111, 0x01, 0x00b50000, false, false],
    [0x2111, 0x02, 0x00b50000, false, false],
    [0x2112, 0x06, 0x00b50000, false, false],
    [0x2112, 0x19, 0x00b50000, false, false],
    [0x2113, 0x01, 0x00b50000, false, false],
    [0x2113, 0x02, 0x00b50000, false, false],
    [0x2213, 0x01, 0x00b50000, false, false],
    [0x2625, 0x02, 0x00b50000, false, false],
    [0x2625, 0x04, 0x00b50000, false, false],
    [0x2630, 0x02, 0x00b50000, false, false],
    [0x2631, 0x02, 0x00b50000, false, false],
    [0x6062, 0x00, 0x00b50000, true, false],
    [0x6064, 0x00, 0x00b50000, true, false],
    [0x6065, 0x00, 0x00b50000, true, false],
    [0x6067, 0x00, 0x00b50000, true, false],
    [0x607a, 0x00, 0x00b50000, true, false],
    [0x607b, 0x01, 0x00b50000, true, false],
    [0x607b, 0x02, 0x00b50000, true, false],
    [0x607c, 0x00, 0x00b50000, true, false],
    [0x607d, 0x01, 0x00b50000, true, false],
    [0x607d, 0x02, 0x00b50000, true, false],
    [0x60f4, 0x00, 0x00b50000, true, false],
    [0x60fc, 0x00, 0x00b50000, true, false],
    // Velocity
    [0x2010, 0x06, 0x00b44700, false, false],
    [0x2010, 0x07, 0x00b44700, false, false],
    [0x2012, 0x04, 0x00b44700, true, true],
    [0x2013, 0x02, 0x00b44700, true, true],
    [0x2013, 0x06, 0x00b44700, true, true],
    [0x2013, 0x0b, 0x00b44700, true, true],
    [0x2013, 0x0f, 0x00b44700, true, true],
    [0x2018, 0x01, 0x00b44700, true, true],
    [0x2018, 0x03, 0x00b44700, true, true],
    [0x2111, 0x03, 0x00b44700, false, true],
    [0x2113, 0x03, 0x00b44700, false, true],
    [0x606b, 0x00, 0x00b44700, true, true],
    [0x606c, 0x00, 0x00b44700, true, true],
    [0x606d, 0x00, 0x00b44700, true, true],
    [0x606f, 0x00, 0x00b44700, true, true],
    [0x6080, 0x00, 0x00b44700, false, true],
    [0x6081, 0x00, 0x00b44700, true, true],
    [0x6099, 0x01, 0x00b44700, true, true],
    [0x6099, 0x02, 0x00b44700, true, true],
    [0x60b1, 0x00, 0x00b44700, true, true],
    [0x60ff, 0x00, 0x00b44700, true, true],
    // Acceleration
    [0x6083, 0x00, 0x00b60300, true, true],
    [0x6084, 0x00, 0x00b60300, true, true],
    [0x6085, 0x00, 0x00b60300, true, true],
    [0x609a, 0x00, 0x00b60300, true, true], // Homing acceleration
];
/**
 * Filters parameters affected by Feed constant, including only position parameters.
 */
exports.feedConstantPositionAffectedParameters = exports.feedConstantAndSiUnitVelocityAffectedParameters
    .filter(([, , unit, affectedByFeedConstant]) => unit === 0x00b50000 && affectedByFeedConstant === true)
    .map(([index, subindex]) => [index, subindex]);
/**
 * Filters parameters affected by SI unit velocity, including both velocity and acceleration parameters excluding position parameters.
 */
exports.siUnitVelocityAffectedParameters = exports.feedConstantAndSiUnitVelocityAffectedParameters
    .filter(([, , unit, , affectedBySiUnitVelocity]) => (unit === 0x00b44700 || unit === 0x00b60300) && affectedBySiUnitVelocity === true)
    .map(([index, subindex]) => [index, subindex]);
/**
 * Filters position parameters affected by the Feed constant, specifically those relevant to interface unit conversion in the UI.
 */
exports.unitConverterPositionParameters = exports.feedConstantAndSiUnitVelocityAffectedParameters
    .filter(([, , unit, affectedByFeedConstant]) => unit === 0x00b50000 && affectedByFeedConstant === true)
    .map(([index, subindex]) => [index, subindex]);
/**
 * Filters velocity parameters affected by the Feed constant, specifically those relevant to interface unit conversion in the UI.
 */
exports.unitConverterVelocityParameters = exports.feedConstantAndSiUnitVelocityAffectedParameters
    .filter(([, , unit, affectedByFeedConstant]) => unit === 0x00b44700 && affectedByFeedConstant === true)
    .map(([index, subindex]) => [index, subindex]);
/**
 * Filters acceleration parameters affected by the Feed constant, specifically those relevant to interface unit conversion in the UI.
 */
exports.unitConverterAccelerationParameters = exports.feedConstantAndSiUnitVelocityAffectedParameters
    .filter(([, , unit, affectedByFeedConstant]) => unit === 0x00b60300 && affectedByFeedConstant === true)
    .map(([index, subindex]) => [index, subindex]);
/**
 * Maps the SI unit velocity value to the corresponding unit symbol.
 */
exports.siUnitVelocityValueToSymbol = {
    // RPM
    [0x0cb44700]: '1e12 RPM',
    [0x09b44700]: '1e9 RPM',
    [0x06b44700]: '1e6 RPM',
    [0x03b44700]: '1e3 RPM',
    [0x00b44700]: 'RPM',
    [0xffb44700]: '1e-1 RPM',
    [0xfeb44700]: '1e-2 RPM',
    [0xfdb44700]: '1e-3 RPM',
    // RPS
    [0x0cb40300]: '1e12 RPS',
    [0x09b40300]: '1e9 RPS',
    [0x06b40300]: '1e6 RPS',
    [0x03b40300]: '1e3 RPS',
    [0x00b40300]: 'RPS',
    [0xffb40300]: '1e-1 RPS',
    [0xfeb40300]: '1e-2 RPS',
    [0xfdb40300]: '1e-3 RPS',
};
exports.symbolToSiUnitVelocityValue = Object.fromEntries(Object.entries(exports.siUnitVelocityValueToSymbol).map(([key, value]) => [value, parseInt(key)]));
/**
 * Parses a given SI Unit Velocity value to extract its scale, type, and unit symbol.
 *
 * This function decodes the given `value` (which represents an SI unit velocity) and returns an object
 * containing the scale factor, unit type (minute or second), and the corresponding unit symbol.
 * The value is validated against predefined SI unit velocity specifications, and errors are thrown if
 * the numerator or denominator are invalid.
 *
 * @param {number} value - The SI Unit Velocity value to be parsed.
 * @returns {SiUnitVelocity} An object containing the parsed scale, type, unit, and value:
 *   - `scale`: The scale factor (e.g., 1e12, 1e-3) based on the prefix.
 *   - `type`: The type of unit, either 'minute' or 'second'.
 *   - `unit`: The unit symbol corresponding to the velocity.
 *   - `value`: The original SI Unit Velocity value.
 * @throws {Error} Throws an error if the numerator or denominator values are invalid for SI Unit Velocity.
 */
function parseSiUnitVelocityValue(value) {
    // Parse the object unit value to get the prefix, numerator, and denominator.
    let { prefix, numerator, denominator } = (0, util_1.parseUnitValue)(value);
    // Check if the numerator value is valid for SI Unit Velocity.
    if (numerator !== 0xb4) {
        console.warn(`The numerator value for the SI Unit Velocity should be revolution (0xb4), but it is: ${numerator}`);
    }
    // Determine the type (minute or second) based on the denominator value.
    let type;
    if (denominator === 0x47) {
        type = 'minute';
    }
    else if (denominator === 0x03) {
        type = 'second';
    }
    // Get a scale factor based on the prefix value.
    const scale = Math.pow(10, prefix > 0x7f ? prefix - 0x100 : prefix);
    // Determine the unit symbol based on the value.
    const unit = exports.siUnitVelocityValueToSymbol[value];
    const siUnitVelocity = {
        scale,
        type,
        unit: unit !== null && unit !== void 0 ? unit : '',
        value,
    };
    return siUnitVelocity;
}
exports.parseSiUnitVelocityValue = parseSiUnitVelocityValue;
/**
 * Use this function when SI unit velocity changes to update the affected parameters.
 * @example When changing from RPM to mRPM, a value of 2,500 will convert to 2,500,000.
 */
function convertSiUnitVelocityAffectedValue(value, oldSiUnitVelocityValue, newSiUnitVelocityValue, round = true) {
    const oldSiUnitVelocity = parseSiUnitVelocityValue(oldSiUnitVelocityValue);
    const newSiUnitVelocity = parseSiUnitVelocityValue(newSiUnitVelocityValue);
    if (oldSiUnitVelocity.type === newSiUnitVelocity.type) {
        value = (oldSiUnitVelocity.scale / newSiUnitVelocity.scale) * value;
    }
    else if (oldSiUnitVelocity.type === 'minute' && newSiUnitVelocity.type === 'second') {
        value = ((oldSiUnitVelocity.scale / newSiUnitVelocity.scale) * value) / 60;
    }
    else if (oldSiUnitVelocity.type === 'second' && newSiUnitVelocity.type === 'minute') {
        value = (oldSiUnitVelocity.scale / newSiUnitVelocity.scale) * value * 60;
    }
    return round ? Math.round(value) : value;
}
exports.convertSiUnitVelocityAffectedValue = convertSiUnitVelocityAffectedValue;
function convertParameterSiUnitVelocityAffectedValue(index, subindex, value, oldSiUnitVelocityValue, newSiUnitVelocityValue, round = true) {
    var _a;
    const [idx, , , , affectedBySiUnitVelocity] = (_a = exports.feedConstantAndSiUnitVelocityAffectedParameters.find(([i, s]) => i === index && s === subindex)) !== null && _a !== void 0 ? _a : [0, 0, 0, false, false];
    if (!affectedBySiUnitVelocity && idx !== 0) {
        return value;
    }
    return convertSiUnitVelocityAffectedValue(value, oldSiUnitVelocityValue, newSiUnitVelocityValue, round);
}
exports.convertParameterSiUnitVelocityAffectedValue = convertParameterSiUnitVelocityAffectedValue;
/**
 * Use this function when the Feed constant changes to update the position affected parameters.
 * Depending on whether the Feed constant gets disabled, enabled, or its value changes, the function will perform conversion, inversion, or scaling.
 */
function convertFeedConstantAffectedPositionValue(value, oldFeedConstant, newFeedConstant, resolution, round = true) {
    if (oldFeedConstant === 0xffffffff && newFeedConstant > 0 && newFeedConstant < 0xffffffff) {
        // conversion
        value = (value * newFeedConstant) / resolution;
    }
    else if (oldFeedConstant > 0 &&
        oldFeedConstant < 0xffffffff &&
        newFeedConstant > 0 &&
        newFeedConstant < 0xffffffff) {
        // scaling
        value = (newFeedConstant / oldFeedConstant) * value;
    }
    else if (oldFeedConstant > 0 && oldFeedConstant < 0xffffffff && newFeedConstant === 0xffffffff) {
        // inversion
        value = (value / oldFeedConstant) * resolution;
    }
    return round ? Math.round(value) : value;
}
exports.convertFeedConstantAffectedPositionValue = convertFeedConstantAffectedPositionValue;
function convertParameterFeedConstantAffectedPositionValue(index, subindex, value, oldFeedConstant, newFeedConstant, resolution, round = true) {
    var _a;
    const [idx, , , affectedByFeedConstant] = (_a = exports.feedConstantAndSiUnitVelocityAffectedParameters.find(([i, s]) => i === index && s === subindex)) !== null && _a !== void 0 ? _a : [0, 0, 0, false, false];
    if (!affectedByFeedConstant && idx !== 0) {
        return value;
    }
    return convertFeedConstantAffectedPositionValue(value, oldFeedConstant, newFeedConstant, resolution, round);
}
exports.convertParameterFeedConstantAffectedPositionValue = convertParameterFeedConstantAffectedPositionValue;
/**
 * Use this function when the Feed constant changes to update the velocity affected parameters.
 * Depending on whether the Feed constant gets disabled, enabled, or its value changes, the function will perform conversion, inversion, or scaling.
 */
function convertFeedConstantAffectedVelocityValue(value, oldFeedConstant, newFeedConstant, round = true) {
    if (oldFeedConstant === 0xffffffff && newFeedConstant > 0 && newFeedConstant < 0xffffffff) {
        // conversion
        value = value * newFeedConstant;
    }
    else if (oldFeedConstant > 0 &&
        oldFeedConstant < 0xffffffff &&
        newFeedConstant > 0 &&
        newFeedConstant < 0xffffffff) {
        // scaling
        value = (newFeedConstant / oldFeedConstant) * value;
    }
    else if (oldFeedConstant > 0 && oldFeedConstant < 0xffffffff && newFeedConstant === 0xffffffff) {
        // inversion
        value = value / oldFeedConstant;
    }
    return round ? Math.round(value) : value;
}
exports.convertFeedConstantAffectedVelocityValue = convertFeedConstantAffectedVelocityValue;
function convertParameterFeedConstantAffectedVelocityValue(index, subindex, value, oldFeedConstant, newFeedConstant, round = true) {
    var _a;
    const [idx, , , affectedByFeedConstant] = (_a = exports.feedConstantAndSiUnitVelocityAffectedParameters.find(([i, s]) => i === index && s === subindex)) !== null && _a !== void 0 ? _a : [0, 0, 0, false, false];
    if (!affectedByFeedConstant && idx !== 0) {
        return value;
    }
    return convertFeedConstantAffectedVelocityValue(value, oldFeedConstant, newFeedConstant, round);
}
exports.convertParameterFeedConstantAffectedVelocityValue = convertParameterFeedConstantAffectedVelocityValue;
/**
 * Adjusts the given value based on the SI unit velocity and Feed constant.
 * It checks if the parameters are influenced by either of these two factors and applies the appropriate conversions.
 *
 * @param {number} index - The index identifying the affected parameter.
 * @param {number} subindex - The subindex identifying the affected parameter.
 * @param {number} value - The value to be adjusted based on the SI unit velocity or Feed constant.
 * @param {number} oldSiUnitVelocity - The original SI unit velocity value.
 * @param {number} newSiUnitVelocity - The new SI unit velocity value to convert to.
 * @param {number} oldFeedConstant - The original Feed constant value.
 * @param {number} newFeedConstant - The new Feed constant value to convert to.
 *
 * @returns {number} The adjusted value after applying the necessary conversions.
 */
function convertParameterVelocityAffectedValue(index, subindex, value, oldSiUnitVelocity, newSiUnitVelocity, oldFeedConstant, newFeedConstant, round = true) {
    value = convertParameterSiUnitVelocityAffectedValue(index, subindex, value, oldSiUnitVelocity, newSiUnitVelocity, round);
    value = convertParameterFeedConstantAffectedVelocityValue(index, subindex, value, oldFeedConstant, newFeedConstant, round);
    return value;
}
exports.convertParameterVelocityAffectedValue = convertParameterVelocityAffectedValue;
/**
 * Represents an instance of a unit converters.
 * Each unit type has dedicated formatter and parser functions:
 * - Formatter: Converts the original value to the desired unit, used for display purposes.
 * - Parser: Converts the value back to the original unit, used for transmitting values to devices in their original unit (e.g., position increments).
 *
 * Options allow selection of the desired unit.
 * Some formatter functions may require additional data, such as motor rated current, for accurate conversion.
 */
exports.unitConverters = {
    acceleration: {
        id: 'acceleration',
        formatter: (unit, value, data) => {
            let feed = data.feed;
            if (!feed) {
                if (unit === 'deg/s²') {
                    feed = 360;
                }
                else if (unit === 'rev/s²') {
                    feed = 1;
                }
            }
            if (!feed) {
                return (0, util_1.toFixedFormat)(value);
            }
            const siUnitVelocity = parseSiUnitVelocityValue(data.siUnitVelocity);
            if (siUnitVelocity.type === 'minute') {
                return (0, util_1.toFixedFormat)(value * (feed / 60) * siUnitVelocity.scale);
            }
            else if (siUnitVelocity.type === 'second') {
                return (0, util_1.toFixedFormat)(value * feed * siUnitVelocity.scale);
            }
            return (0, util_1.toFixedFormat)(value);
        },
        options: [
            { value: 'RPM/s', text: 'Revolutions per minute per second (native)' },
            { value: 'deg/s²', text: 'Degrees per second squared' },
            { value: 'rev/s²', text: 'Revolutions per second squared' },
        ],
        parser: (unit, value, data) => {
            value = typeof value === 'string' ? parseFloat(value) : value;
            let feed = data.feed;
            if (!feed) {
                if (unit === 'deg/s²') {
                    feed = 360;
                }
                else if (unit === 'rev/s²') {
                    feed = 1;
                }
            }
            if (!feed) {
                return value;
            }
            const siUnitVelocity = parseSiUnitVelocityValue(data.siUnitVelocity);
            if (siUnitVelocity.type === 'minute') {
                return Math.round((value / (feed / 60)) * (1 / siUnitVelocity.scale));
            }
            else if (siUnitVelocity.type === 'second') {
                return Math.round((value / feed) * (1 / siUnitVelocity.scale));
            }
            return Math.round(value);
        },
    },
    current: {
        id: 'current',
        formatter: (unit, value, data) => {
            if (unit === 'mA') {
                return (0, util_1.toFixedFormat)(Math.round((value / 1e3) * data.motorRatedCurrent));
            }
            else if (unit === 'A') {
                return (0, util_1.toFixedFormat)(Math.round(((value / 1e3) * data.motorRatedCurrent) / 1e3));
            }
            else {
                return (0, util_1.toFixedFormat)(value);
            }
        },
        options: [
            { value: '‰', text: 'Per mille (native)' },
            { value: 'mA', text: 'Milliampere' },
            { value: 'A', text: 'Ampere' },
        ],
        parser: (unit, value, data) => {
            value = typeof value === 'string' ? parseFloat(value) : value;
            if (unit === 'mA') {
                return (value / data.motorRatedCurrent) * 1e3;
            }
            else if (unit === 'A') {
                return (value / data.motorRatedCurrent) * 1e6;
            }
            else {
                return value;
            }
        },
    },
    friction: {
        id: 'friction',
        formatter: (unit, value) => {
            if (unit === 'Nm/kRPM') {
                return (0, util_1.toFixedFormat)(value * 104.71975511965977); // (2 * Math.PI * 1000 / 60)
            }
            else {
                return (0, util_1.toFixedFormat)(value);
            }
        },
        options: [
            { value: 'Nm/(rad/s)', text: 'Nm/(rad/s)' },
            { value: 'Nm/kRPM', text: 'Nm/kRPM' },
        ],
        parser: (unit, value) => {
            value = typeof value === 'string' ? parseFloat(value) : value;
            if (unit === 'Nm/kRPM') {
                return value / 104.71975511965977; // (2 * Math.PI * 1000 / 60)
            }
            else {
                return value;
            }
        },
    },
    inertia: {
        id: 'inertia',
        formatter: (unit, value) => {
            if (unit === 'g cm²') {
                return (0, util_1.toFixedFormat)(value * 1e7);
            }
            else if (unit === 'kg cm²') {
                return (0, util_1.toFixedFormat)(value * 1e4);
            }
            else {
                return (0, util_1.toFixedFormat)(value);
            }
        },
        options: [
            { value: 'kg m²', text: 'kg m²' },
            { value: 'g cm²', text: 'g cm²' },
            { value: 'kg cm²', text: 'kg cm²' },
        ],
        parser: (unit, value) => {
            value = typeof value === 'string' ? parseFloat(value) : value;
            if (unit === 'g cm²') {
                return value / 1e7;
            }
            else if (unit === 'kg cm²') {
                return value / 1e4;
            }
            else {
                return value;
            }
        },
    },
    position: {
        id: 'position',
        formatter: (unit, value, data) => {
            let feed = data.feed;
            if (!feed) {
                if (unit === 'deg') {
                    feed = 360;
                }
                else if (unit === 'mdeg') {
                    feed = 360000;
                }
                else if (unit === 'rev') {
                    feed = 1;
                }
            }
            if (!feed) {
                return (0, util_1.toFixedFormat)(value);
            }
            return (0, util_1.toFixedFormat)((value / data.resolution) * feed);
        },
        options: [
            { value: 'inc', text: 'Increments (native)' },
            { value: 'deg', text: 'Degrees' },
            { value: 'mdeg', text: 'Millidegrees' },
            { value: 'rev', text: 'Revolutions' },
        ],
        parser: (unit, value, data) => {
            value = typeof value === 'string' ? parseFloat(value) : value;
            let feed = data.feed;
            if (!feed) {
                if (unit === 'deg') {
                    feed = 360;
                }
                else if (unit === 'mdeg') {
                    feed = 360000;
                }
                else if (unit === 'rev') {
                    feed = 1;
                }
            }
            if (!feed) {
                return value;
            }
            return Math.round((value / feed) * data.resolution);
        },
    },
    resistance: {
        id: 'resistance',
        formatter: (unit, value) => {
            if (unit === 'Ω') {
                return (0, util_1.toFixedFormat)(value / 1e6);
            }
            else if (unit === 'mΩ') {
                return (0, util_1.toFixedFormat)(value / 1e3);
            }
            else {
                return (0, util_1.toFixedFormat)(value);
            }
        },
        options: [
            { value: 'μΩ', text: 'Micro-ohm' },
            { value: 'mΩ', text: 'Milliohm' },
            { value: 'Ω', text: 'Ohm' },
        ],
        parser: (unit, value) => {
            value = typeof value === 'string' ? parseFloat(value) : value;
            if (unit === 'Ω') {
                return value * 1e6;
            }
            else if (unit === 'mΩ') {
                return value * 1e3;
            }
            else {
                return value;
            }
        },
    },
    inductance: {
        id: 'inductance',
        formatter: (unit, value) => {
            if (unit === 'H') {
                return (0, util_1.toFixedFormat)(value / 1000 / 1000);
            }
            else if (unit === 'mH') {
                return (0, util_1.toFixedFormat)(value / 1000);
            }
            else {
                return (0, util_1.toFixedFormat)(value);
            }
        },
        options: [
            { value: 'μH', text: 'Microhenry' },
            { value: 'mH', text: 'Millihenry' },
            { value: 'H', text: 'Henry' },
        ],
        parser: (unit, value) => {
            value = typeof value === 'string' ? parseFloat(value) : value;
            if (unit === 'H') {
                return value * 1e6;
            }
            else if (unit === 'mH') {
                return value * 1e3;
            }
            else {
                return value;
            }
        },
    },
    motorRatedCurrent: {
        id: 'motorRatedCurrent',
        formatter: (unit, value) => {
            if (unit === 'A') {
                return (0, util_1.toFixedFormat)(value / 1e3);
            }
            else {
                return (0, util_1.toFixedFormat)(value);
            }
        },
        options: [
            { value: 'mA', text: 'Milliampere' },
            { value: 'A', text: 'Ampere' },
        ],
        parser: (unit, value) => {
            value = typeof value === 'string' ? parseFloat(value) : value;
            if (unit === 'A') {
                return value * 1e3;
            }
            else {
                return value;
            }
        },
    },
    torque: {
        id: 'torque',
        formatter: (unit, value, data) => {
            if (unit === 'mNm') {
                return (0, util_1.toFixedFormat)(Math.round((value / 1000) * data.motorRatedTorque));
            }
            else {
                return (0, util_1.toFixedFormat)(value);
            }
        },
        options: [
            { value: '‰', text: 'Per mille (native)' },
            { value: 'mNm', text: 'Millinewton meter' },
        ],
        parser: (unit, value, data) => {
            value = typeof value === 'string' ? parseFloat(value) : value;
            if (unit === 'mNm') {
                return (value / data.motorRatedTorque) * 1000;
            }
            else {
                return value;
            }
        },
    },
    torqueConstant: {
        id: 'torqueConstant',
        formatter: (unit, value) => {
            if (unit === 'Nm/A') {
                return (0, util_1.toFixedFormat)(value / 1e6);
            }
            else if (unit === 'mNm/A') {
                return (0, util_1.toFixedFormat)(value / 1e3);
            }
            else {
                return (0, util_1.toFixedFormat)(value);
            }
        },
        options: [
            { value: 'μNm/A', text: 'Micronewton per ampere (RMS)' },
            { value: 'mNm/A', text: 'Millinewton per ampere (RMS)' },
            { value: 'Nm/A', text: 'Newton per ampere (RMS)' },
        ],
        parser: (unit, value) => {
            value = typeof value === 'string' ? parseFloat(value) : value;
            if (unit === 'Nm/A') {
                return value * 1e6;
            }
            else if (unit === 'mNm/A') {
                return value * 1e3;
            }
            else {
                return value;
            }
        },
    },
    velocity: {
        id: 'velocity',
        formatter: (unit, value, data) => {
            let feed = data.feed;
            if (!feed) {
                if (unit === 'deg/s') {
                    feed = 360;
                }
                else if (unit === 'rev/s') {
                    feed = 1;
                }
            }
            if (!feed) {
                return (0, util_1.toFixedFormat)(value);
            }
            const siUnitVelocity = parseSiUnitVelocityValue(data.siUnitVelocity);
            if (siUnitVelocity.type === 'minute') {
                return (0, util_1.toFixedFormat)(value * (feed / 60) * siUnitVelocity.scale);
            }
            else if (siUnitVelocity.type === 'second') {
                return (0, util_1.toFixedFormat)(value * feed * siUnitVelocity.scale);
            }
            return (0, util_1.toFixedFormat)(value);
        },
        options: [
            // The 'RPM' unit should be updated in the UI to reflect the appropriate SI unit for velocity.
            { value: 'RPM', text: 'Revolutions per minute (native)' },
            { value: 'deg/s', text: 'Degrees per second' },
            { value: 'rev/s', text: 'Revolutions per second' },
        ],
        parser: (unit, value, data) => {
            value = typeof value === 'string' ? parseFloat(value) : value;
            let feed = data.feed;
            if (!feed) {
                if (unit === 'deg/s') {
                    feed = 360;
                }
                else if (unit === 'rev/s') {
                    feed = 1;
                }
            }
            if (!feed) {
                return value;
            }
            const siUnitVelocity = parseSiUnitVelocityValue(data.siUnitVelocity);
            if (siUnitVelocity.type === 'minute') {
                return Math.round((value / (feed / 60)) * (1 / siUnitVelocity.scale));
            }
            else if (siUnitVelocity.type === 'second') {
                return Math.round((value / feed) * (1 / siUnitVelocity.scale));
            }
            return Math.round(value);
        },
    },
};
exports.unitConverterParameters = {
    acceleration: exports.unitConverterAccelerationParameters,
    current: [
        [0x6073, 0], // Max current
    ],
    friction: [],
    inductance: [
        [0x2003, 4], // Phase inductance
    ],
    inertia: [],
    motorRatedCurrent: [
        [0x6075, 0], // Motor rated current
    ],
    position: [
        ...exports.unitConverterPositionParameters,
        [0x2004, 8], // Minimum displacement (pin brake)
    ],
    resistance: [
        [0x2003, 3], // Phase resistance
    ],
    torque: [
        [0x6071, 0],
        [0x6072, 0],
        [0x6074, 0],
        [0x6077, 0],
        [0x60b2, 0], // Torque offset
    ],
    torqueConstant: [
        [0x2003, 2], // Torque constant
    ],
    velocity: exports.unitConverterVelocityParameters,
};
/**
 * Get the unit converter for a given parameter index and subindex.
 */
function getUnitConverterForParameter(index, subindex) {
    for (const [key, values] of Object.entries(exports.unitConverterParameters)) {
        for (const [i, s] of values) {
            if (i === index && s === subindex) {
                return exports.unitConverters[key];
            }
        }
    }
    return;
}
exports.getUnitConverterForParameter = getUnitConverterForParameter;
/**
 * Formats the unit display based on feed constant settings and SI unit velocity scaling.
 *
 * @param {string} unit - The unit to be formatted (e.g., "RPM").
 * @param {number} siUnitVelocityValue - The SI unit velocity value used for velocity or acceleration scaling.
 * @param {boolean} [feedConstantEnabled] - A flag indicating whether the feed constant is enabled.
 * @param {string} [feedConstantUnit] - The unit of the feed constant (e.g., "mm", "inches").
 *
 * @returns {string} The formatted unit display.
 */
function getFormattedUnitDisplay(unit, siUnitVelocityValue, feedConstantEnabled, feedConstantUnit, affectedByFeedConstant = false, affectedBySiUnitVelocity = false) {
    if (!unit) {
        return '';
    }
    let out = unit;
    const lcunit = unit.toLowerCase();
    const siUnitVelocity = parseSiUnitVelocityValue(siUnitVelocityValue);
    const isRPM = siUnitVelocity.type === 'minute';
    const isRPS = siUnitVelocity.type === 'second';
    if (feedConstantEnabled && affectedByFeedConstant) {
        if (lcunit === 'inc') {
            return feedConstantUnit || 'feed';
        }
        else if (lcunit === 'rpm') {
            out = '';
            const { scale } = siUnitVelocity;
            if (scale && scale !== 1) {
                out = scale.toExponential() + ' '; // 1e-3
            }
            out += (feedConstantUnit || 'feed') + '/'; // 1e-3 feed/
            if (isRPM) {
                out += 'min'; // 1e-3 feed/min
            }
            else if (isRPS) {
                out += 's'; // 1e-3 feed/s
            }
            return out;
        }
        else if (lcunit === 'rpm/s') {
            out = '';
            const { scale } = siUnitVelocity;
            if (scale && scale !== 1) {
                out = scale.toExponential() + ' '; // 1e-3
            }
            out += (feedConstantUnit || 'feed') + '/'; // 1e-3 feed/
            if (isRPM) {
                out += 'min/s'; // 1e-3 feed/min/s
            }
            else if (isRPS) {
                out += 's²'; // 1e-3 feed/s²
            }
        }
    }
    else if (affectedBySiUnitVelocity) {
        if (lcunit === 'rpm' && siUnitVelocity.unit) {
            out = siUnitVelocity.unit.toLowerCase(); // 1e-3 rpm
        }
        else if (lcunit === 'rpm/s' && siUnitVelocity.unit) {
            if (siUnitVelocity.type === 'minute') {
                out = siUnitVelocity.unit.toLowerCase() + '/s'; // 1e-3 rpm/s
            }
            else if (siUnitVelocity.type === 'second') {
                out = siUnitVelocity.unit.toLowerCase().replace('rps', 'rps²'); // 1e-3 rps²
            }
        }
    }
    return out;
}
exports.getFormattedUnitDisplay = getFormattedUnitDisplay;
/**
 * Determines the formatted unit display for a parameter, considering feed constant settings.
 *
 * This function checks whether a parameter (identified by `index` and `subindex`)
 * should have its unit transformed based on feed constant settings. If the feed constant
 * is enabled and the parameter is not in the list of unaffected parameters, it applies
 * formatting using `getFormattedUnitDisplay`. Otherwise, it returns the original unit.
 *
 * @param {number} index - The parameter index.
 * @param {number} subindex - The parameter subindex.
 * @param {string} unit - The base unit of the parameter (e.g., "Inc").
 * @param {number} siUnitVelocityValue - The SI unit velocity value used for velocity or acceleration scaling.
 * @param {boolean} [feedConstantEnabled] - A flag indicating whether the feed constant is enabled.
 * @param {string} [feedConstantUnit] - The unit of the feed constant (e.g., "mm", "inches").
 *
 * @returns {string} The formatted unit display if the feed constant applies, otherwise the original unit.
 */
function getParameterFormattedUnitDisplay(index, subindex, unit, siUnitVelocityValue, feedConstantEnabled, feedConstantUnit) {
    var _a;
    let [, , , affectedByFeedConstant, affectedBySiUnitVelocity] = (_a = exports.feedConstantAndSiUnitVelocityAffectedParameters.find(([i, s]) => i === index && s === subindex)) !== null && _a !== void 0 ? _a : [0, 0, 0, true, true];
    return getFormattedUnitDisplay(unit, siUnitVelocityValue, feedConstantEnabled, feedConstantUnit, affectedByFeedConstant, affectedBySiUnitVelocity);
}
exports.getParameterFormattedUnitDisplay = getParameterFormattedUnitDisplay;
//# sourceMappingURL=units.js.map