export default class UnitHelper {
    static #CHRONO_UNITS = [
        'ms',
        's',
        'm',
        'h',
        'd',
        'y'
    ];

    static #CHRONO_UNIT_FACTOR = [
        1000, 
        60, 
        60, 
        24, 
        365
    ]

    static #CHRONO_UNIT_TO_MS_MAPPING = new Map([
        ['ms', 1],
        ['s', 1000],
        ['m', 60000],
        ['h', 3600000],
        ['d', 3600000 * 24],
        ['y', 3600000 * 24 * 365],
    ]);


    /**
     * Converts milliseconds to a formated chonological unit representation.
     * Examples:
     * 1 => '1 ms'
     * 1000 => '1 s'
     * 1234 => '1.23 s'
     * 60000 => '1 m'
     * 
     * Available units: ['ms', 's', 'm', 'h', 'd', 'y']
     * 
     * @param {number} durationInMs 
     * @returns {string}
     */
    static getFormatedDuration(durationInMs) {
        let remaining = durationInMs;
        let index = 0;

        while (index < UnitHelper.#CHRONO_UNIT_FACTOR.length && remaining > UnitHelper.#CHRONO_UNIT_FACTOR[index]) {
            remaining = Math.round(((remaining / UnitHelper.#CHRONO_UNIT_FACTOR[index]) + Number.EPSILON) * 100) / 100;
            index++;
        }

        return remaining + " " + UnitHelper.#CHRONO_UNITS[index];
    }

    /**
     * Converts a formated duration to milliseconds.
     * Format: '\d+( (ms|s|m|h|d|y))?'
     * 
     * Examples:
     * '2 m' => 120000
     * '12 ms' => 12
     * '5 s' => 5000
     * 
     * @param {string | number} duration 
     * @returns {number}
     */
    static formatedDurationToMs(duration) {
        if (typeof duration === 'number') {
            return duration;
        }

        const regex = /^(\d+)([a-zA-Z]+)$/;
        const match = duration.toLowerCase().replace(" ", "").match(regex);

        if (match) {
            return match[1] * UnitHelper.#CHRONO_UNIT_TO_MS_MAPPING.get(match[2]);
        } else {
            return 0;
        }
    }
}