"use strict";

import { BigNumber, BigNumberish, formatFixed, parseFixed } from "@ethersproject/bignumber";
import { Logger } from "@ethersproject/logger";
import { version } from "./_version";
const logger = new Logger(version);

const names = [
    "tinybar",
    "microbar",
    "millibar",
    "hbar",
    "kilobar",
    "megabar",
    "gigabar",
];


// Some environments have issues with RegEx that contain back-tracking, so we cannot
// use them.
export function commify(value: string | number): string {
    const comps = String(value).split(".");

    if (comps.length > 2 || !comps[0].match(/^-?[0-9]*$/) || (comps[1] && !comps[1].match(/^[0-9]*$/)) || value === "." || value === "-.") {
        logger.throwArgumentError("invalid value", "value", value);
    }

    // Make sure we have at least one whole digit (0 if none)
    let whole = comps[0];

    let negative = "";
    if (whole.substring(0, 1) === "-") {
        negative = "-";
        whole = whole.substring(1);
    }

    // Make sure we have at least 1 whole digit with no leading zeros
    while (whole.substring(0, 1) === "0") { whole = whole.substring(1); }
    if (whole === "") { whole = "0"; }

    let suffix = "";
    if (comps.length === 2) { suffix = "." + (comps[1] || "0"); }
    while (suffix.length > 2 && suffix[suffix.length - 1] === "0") {
        suffix = suffix.substring(0, suffix.length - 1);
    }

    const formatted = [];
    while (whole.length) {
        if (whole.length <= 3) {
            formatted.unshift(whole);
            break;
        } else {
            const index = whole.length - 3;
            formatted.unshift(whole.substring(index));
            whole = whole.substring(0, index);
        }
    }

    return negative + formatted.join(",") + suffix;
}

export function formatUnits(value: BigNumberish, unitName?: string | BigNumberish): string {
    if (typeof(unitName) === "string") {
        const index = names.indexOf(unitName);
        if (index !== -1) { unitName = Math.max((3 * index) - 1, 0); }
    }
    return formatFixed(value, (unitName != null) ? unitName: 8);
}

export function parseUnits(value: string, unitName?: BigNumberish): BigNumber {
    if (typeof(value) !== "string") {
        logger.throwArgumentError("value must be a string", "value", value);
    }
    if (typeof(unitName) === "string") {
        const index = names.indexOf(unitName);
        if (index !== -1) { unitName = Math.max((3 * index) - 1, 0); }
    }
    return parseFixed(value, (unitName != null) ? unitName: 8);
}

export function formatHbar(tinybar: BigNumberish): string {
    return formatUnits(tinybar, 8);
}

export function parseHbar(hbar: string): BigNumber {
    return parseUnits(hbar, 8);
}