"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.round = round;
exports.calculateQuantums = calculateQuantums;
exports.calculateVaultQuantums = calculateVaultQuantums;
exports.calculateSubticks = calculateSubticks;
exports.calculateSide = calculateSide;
exports.calculateTimeInForce = calculateTimeInForce;
exports.calculateOrderFlags = calculateOrderFlags;
exports.calculateClientMetadata = calculateClientMetadata;
exports.calculateConditionType = calculateConditionType;
exports.calculateConditionalOrderTriggerSubticks = calculateConditionalOrderTriggerSubticks;
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const long_1 = __importDefault(require("long"));
const constants_1 = require("../constants");
const proto_includes_1 = require("../modules/proto-includes");
const types_1 = require("../types");
function round(input, base) {
    return (0, bignumber_js_1.default)(input)
        .div((0, bignumber_js_1.default)(base))
        .integerValue(bignumber_js_1.default.ROUND_FLOOR)
        .times((0, bignumber_js_1.default)(base))
        .toNumber();
}
function calculateQuantums(size, atomicResolution, stepBaseQuantums) {
    const rawQuantums = (0, bignumber_js_1.default)(size).times((0, bignumber_js_1.default)(10).pow((0, bignumber_js_1.default)(atomicResolution).negated()));
    const quantums = round(rawQuantums.toNumber(), stepBaseQuantums);
    // stepBaseQuantums functions as minimum order size
    const result = Math.max(quantums, stepBaseQuantums);
    return long_1.default.fromNumber(result);
}
function calculateVaultQuantums(size) {
    return BigInt((0, bignumber_js_1.default)(size).times(1000000).toFixed(0, bignumber_js_1.default.ROUND_FLOOR));
}
function calculateSubticks(price, atomicResolution, quantumConversionExponent, subticksPerTick) {
    const QUOTE_QUANTUMS_ATOMIC_RESOLUTION = -6;
    const exponent = atomicResolution - quantumConversionExponent - QUOTE_QUANTUMS_ATOMIC_RESOLUTION;
    const rawSubticks = (0, bignumber_js_1.default)(price).times((0, bignumber_js_1.default)(10).pow(exponent));
    const subticks = round(rawSubticks.toNumber(), subticksPerTick);
    const result = Math.max(subticks, subticksPerTick);
    return long_1.default.fromNumber(result);
}
function calculateSide(side) {
    return side === constants_1.OrderSide.BUY ? proto_includes_1.Order_Side.SIDE_BUY : proto_includes_1.Order_Side.SIDE_SELL;
}
function calculateTimeInForce(type, timeInForce, execution, postOnly) {
    switch (type) {
        case constants_1.OrderType.MARKET:
            switch (timeInForce) {
                case constants_1.OrderTimeInForce.FOK:
                    return proto_includes_1.Order_TimeInForce.TIME_IN_FORCE_FILL_OR_KILL;
                default:
                    return proto_includes_1.Order_TimeInForce.TIME_IN_FORCE_IOC;
            }
        case constants_1.OrderType.LIMIT:
            switch (timeInForce) {
                case constants_1.OrderTimeInForce.GTT:
                    if (postOnly == null) {
                        throw new Error('postOnly must be set if order type is LIMIT and timeInForce is GTT');
                    }
                    return postOnly
                        ? proto_includes_1.Order_TimeInForce.TIME_IN_FORCE_POST_ONLY
                        : proto_includes_1.Order_TimeInForce.TIME_IN_FORCE_UNSPECIFIED;
                case constants_1.OrderTimeInForce.FOK:
                    return proto_includes_1.Order_TimeInForce.TIME_IN_FORCE_FILL_OR_KILL;
                case constants_1.OrderTimeInForce.IOC:
                    return proto_includes_1.Order_TimeInForce.TIME_IN_FORCE_IOC;
                default:
                    throw new Error('Unexpected code path: timeInForce');
            }
        case constants_1.OrderType.STOP_LIMIT:
        case constants_1.OrderType.TAKE_PROFIT_LIMIT:
            if (execution == null) {
                throw new Error('execution must be set if order type is STOP_LIMIT or TAKE_PROFIT_LIMIT');
            }
            switch (execution) {
                case constants_1.OrderExecution.DEFAULT:
                    return proto_includes_1.Order_TimeInForce.TIME_IN_FORCE_UNSPECIFIED;
                case constants_1.OrderExecution.POST_ONLY:
                    return proto_includes_1.Order_TimeInForce.TIME_IN_FORCE_POST_ONLY;
                case constants_1.OrderExecution.FOK:
                    return proto_includes_1.Order_TimeInForce.TIME_IN_FORCE_FILL_OR_KILL;
                case constants_1.OrderExecution.IOC:
                    return proto_includes_1.Order_TimeInForce.TIME_IN_FORCE_IOC;
                default:
                    throw new Error('Unexpected code path: timeInForce');
            }
        case constants_1.OrderType.STOP_MARKET:
        case constants_1.OrderType.TAKE_PROFIT_MARKET:
            if (execution == null) {
                throw new Error('execution must be set if order type is STOP_MARKET or TAKE_PROFIT_MARKET');
            }
            switch (execution) {
                case constants_1.OrderExecution.DEFAULT:
                    throw new Error('Execution value DEFAULT not supported for STOP_MARKET or TAKE_PROFIT_MARKET');
                case constants_1.OrderExecution.POST_ONLY:
                    throw new Error('Execution value POST_ONLY not supported for STOP_MARKET or TAKE_PROFIT_MARKET');
                case constants_1.OrderExecution.FOK:
                    return proto_includes_1.Order_TimeInForce.TIME_IN_FORCE_FILL_OR_KILL;
                case constants_1.OrderExecution.IOC:
                    return proto_includes_1.Order_TimeInForce.TIME_IN_FORCE_IOC;
                default:
                    throw new Error('Unexpected code path: timeInForce');
            }
        default:
            throw new Error('Unexpected code path: timeInForce');
    }
}
function calculateOrderFlags(type, timeInForce) {
    switch (type) {
        case constants_1.OrderType.MARKET:
            return types_1.OrderFlags.SHORT_TERM;
        case constants_1.OrderType.LIMIT:
            if (timeInForce === undefined) {
                throw new Error('timeInForce must be set if orderType is LIMIT');
            }
            if (timeInForce === constants_1.OrderTimeInForce.GTT) {
                return types_1.OrderFlags.LONG_TERM;
            }
            else {
                return types_1.OrderFlags.SHORT_TERM;
            }
        case constants_1.OrderType.STOP_LIMIT:
        case constants_1.OrderType.TAKE_PROFIT_LIMIT:
        case constants_1.OrderType.STOP_MARKET:
        case constants_1.OrderType.TAKE_PROFIT_MARKET:
            return types_1.OrderFlags.CONDITIONAL;
        default:
            throw new Error('Unexpected code path: orderFlags');
    }
}
function calculateClientMetadata(orderType) {
    switch (orderType) {
        case constants_1.OrderType.MARKET:
        case constants_1.OrderType.STOP_MARKET:
        case constants_1.OrderType.TAKE_PROFIT_MARKET:
            return 1;
        default:
            return 0;
    }
}
function calculateConditionType(orderType) {
    switch (orderType) {
        case constants_1.OrderType.LIMIT:
            return proto_includes_1.Order_ConditionType.CONDITION_TYPE_UNSPECIFIED;
        case constants_1.OrderType.MARKET:
            return proto_includes_1.Order_ConditionType.CONDITION_TYPE_UNSPECIFIED;
        case constants_1.OrderType.STOP_LIMIT:
        case constants_1.OrderType.STOP_MARKET:
            return proto_includes_1.Order_ConditionType.CONDITION_TYPE_STOP_LOSS;
        case constants_1.OrderType.TAKE_PROFIT_LIMIT:
        case constants_1.OrderType.TAKE_PROFIT_MARKET:
            return proto_includes_1.Order_ConditionType.CONDITION_TYPE_TAKE_PROFIT;
        default:
            return proto_includes_1.Order_ConditionType.CONDITION_TYPE_UNSPECIFIED;
    }
}
function calculateConditionalOrderTriggerSubticks(orderType, atomicResolution, quantumConversionExponent, subticksPerTick, triggerPrice) {
    switch (orderType) {
        case constants_1.OrderType.LIMIT:
        case constants_1.OrderType.MARKET:
            return long_1.default.fromNumber(0);
        case constants_1.OrderType.STOP_LIMIT:
        case constants_1.OrderType.STOP_MARKET:
        case constants_1.OrderType.TAKE_PROFIT_LIMIT:
        case constants_1.OrderType.TAKE_PROFIT_MARKET:
            if (triggerPrice === undefined) {
                throw new Error('triggerPrice must be set if orderType is STOP_LIMIT, STOP_MARKET, TAKE_PROFIT_LIMIT, or TAKE_PROFIT_MARKET');
            }
            return calculateSubticks(triggerPrice, atomicResolution, quantumConversionExponent, subticksPerTick);
        default:
            return long_1.default.fromNumber(0);
    }
}
//# sourceMappingURL=data:application/json;base64, 