import { BigNumber } from "./BigNumberUtils";
import { isDefined } from "./TypeGuards";
/**
 * This function converts a JSON string into a JSON object. The caveat is that if
 * the parser detects a number, it will convert it to a string and floor it to
 * an integer. This function will not throw but instead return an undefined value
 * if the JSON string is invalid.
 * @param jsonString The JSON string to parse
 * @returns The parsed JSON object or undefined if the JSON string is invalid
 */
export function parseJSONWithNumericString(jsonString) {
    try {
        return JSON.parse(jsonString, (_key, value) => {
            if (typeof value === "number") {
                return String(Math.floor(value));
            }
            return value;
        });
    }
    catch {
        return undefined;
    }
}
/**
 * This function converts an object into a JSON string. The caveat is that if
 * the parser detects a BigNumber or BN, it will convert it to a string.
 * @param obj The object to stringify
 * @returns The stringified JSON object
 * @throws Error if the object cannot be stringified
 */
export function stringifyJSONWithNumericString(obj) {
    return JSON.stringify(obj, (_key, value) => {
        if (typeof value === "object" && value !== null && value.type === "BigNumber") {
            return BigNumber.from(value).toString();
        }
        else if (typeof value === "bigint" && value !== null) {
            return value.toString();
        }
        return value;
    });
}
/**
 * A replacer for use in `JSON.stringify` that converts big numbers to numeric strings.
 * @param _key Unused
 * @param value The value to convert
 * @returns The converted value
 */
export function jsonReplacerWithBigNumbers(_key, value) {
    // If the value is not defined (null or undefined), return it as is
    if (!isDefined(value)) {
        return value;
    }
    // We need to check if this is a big number, because the JSON parser
    // is not aware of BigNumbers and will convert them to the string representation
    // of the object itself which is not what we want.
    if (BigNumber.isBigNumber(value) || typeof value === "bigint") {
        return value.toString();
    }
    // There's a legacy issues that returns BigNumbers as { type: "BigNumber", hex: "0x..." }
    // so we need to check for that as well.
    const recordValue = value;
    if (recordValue.type === "BigNumber" && isDefined(recordValue.hex)) {
        return BigNumber.from(recordValue.hex).toString();
    }
    // Return the value as is
    return value;
}
/**
 * A reviver for use in `JSON.parse` that converts numeric strings to big numbers.
 * @param _key Unused
 * @param value The value to convert
 * @returns The converted value
 */
export function jsonReviverWithBigNumbers(_key, value) {
    // We need to check for both strings and big numbers, because the JSON parser
    // is not aware of BigNumbers.
    if (typeof value === "string" && /^-?\d+$/.test(value)) {
        const bigNumber = BigNumber.from(value);
        if (bigNumber.toString() === value) {
            return bigNumber;
        }
    }
    return value;
}
/**
 * A replacer for `JSON.stringify` that converts BigInt to a decimal string with 'n' suffix.
 */
export function jsonReplacerWithBigInts(_key, value) {
    return typeof value === "bigint" ? value.toString() + "n" : value;
}
/**
 * A reviver for `JSON.parse` that converts strings ending in 'n' back to BigInt.
 */
export function jsonReviverWithBigInts(_key, value) {
    return typeof value === "string" && /^-?\d+n$/.test(value) ? BigInt(value.slice(0, -1)) : value;
}
//# sourceMappingURL=JSONUtils.js.map