"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.reverseRangeIndex = exports.projectRangeIndex = exports.inferDynamicRange = exports.toRangeRaw = exports.fromRangeRaw = void 0;
// Utility to deal with ranges
const bignumber_js_1 = require("bignumber.js");
function fromRangeRaw(r) {
    return {
        initial: new bignumber_js_1.BigNumber(r.initial),
        min: new bignumber_js_1.BigNumber(r.min),
        max: new bignumber_js_1.BigNumber(r.max),
        step: new bignumber_js_1.BigNumber(r.step),
        steps: r.steps,
    };
}
exports.fromRangeRaw = fromRangeRaw;
function toRangeRaw(r) {
    return {
        initial: r.initial.toString(),
        min: r.min.toString(),
        max: r.max.toString(),
        step: r.step.toString(),
        steps: r.steps,
    };
}
exports.toRangeRaw = toRangeRaw;
const defaultOpts = {
    minMult: 0.3,
    maxMult: 2,
    targetSteps: 20,
};
// infer a range from ONE estimated fees value.
// e.g. we just have a "gasPrice" and we want a slider to move a gas value around it.
// to test this:
// for (let i = 0.1; i < 10; i += 0.1) console.log(i, inferDynamicRange(i));
function inferDynamicRange(amount, opts = {}) {
    const { minMult, maxMult, targetSteps, minValue, maxValue } = {
        ...defaultOpts,
        ...opts,
    };
    const targetMin = minValue || amount.times(minMult);
    const targetMax = maxValue || amount.times(maxMult);
    const step = findBestRangeStep(targetMin, targetMax, targetSteps);
    if (Number.isNaN(step) || step.lte(0)) {
        throw new Error("inferDynamicRange: invalid parameters");
    }
    const initial = stepping(amount, step, bignumber_js_1.BigNumber.ROUND_CEIL);
    const min = stepping(targetMin, step, bignumber_js_1.BigNumber.ROUND_CEIL);
    const max = stepping(targetMax, step, bignumber_js_1.BigNumber.ROUND_CEIL);
    const steps = max.minus(min).div(step).plus(1).toNumber();
    return {
        initial,
        min,
        max,
        step,
        steps,
    };
}
exports.inferDynamicRange = inferDynamicRange;
function projectRangeIndex(range, index) {
    return range.min.plus(range.step.times(index));
}
exports.projectRangeIndex = projectRangeIndex;
function reverseRangeIndex(range, n) {
    const x = n.minus(range.min).div(range.max.minus(range.min));
    const i = x.times(range.steps).integerValue(bignumber_js_1.BigNumber.ROUND_FLOOR).toNumber();
    return Math.max(0, Math.min(i, range.steps - 1));
}
exports.reverseRangeIndex = reverseRangeIndex;
function stepping(n, step, roundingMode) {
    return n.div(step).integerValue(roundingMode).times(step);
}
const log10 = Math.log(10);
// return step to use for a [min,max] with a planned number of steps (will approx).
function findBestRangeStep(min, max, steps) {
    const nonRoundedStep = (max.toNumber() - min.toNumber()) / steps;
    const mag = Math.log(nonRoundedStep) / log10;
    const magInt = Math.floor(mag);
    const remain = mag - magInt;
    let step = new bignumber_js_1.BigNumber(10).pow(magInt);
    // heuristics
    if (remain < 0.3) {
        step = step.div(5);
    }
    else if (remain < 0.7) {
        step = step.div(2);
    }
    return step;
}
//# sourceMappingURL=range.js.map