"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.duplicateEvent = exports.getTransactionRefs = exports.isEventOlder = exports.sortEventsDescendingInPlace = exports.sortEventsDescending = exports.sortEventsAscendingInPlace = exports.sortEventsAscending = exports.spreadEventWithBlockNumber = exports.logToSortableEvent = exports.getPaginatedBlockRanges = exports.paginatedEventQuery = exports.eventToLog = exports.spreadEvent = void 0;
var tslib_1 = require("tslib");
var common_1 = require("./common");
var _1 = require("./");
var maxRetries = 3;
var retrySleepTime = 10;
function spreadEvent(args) {
    var keys = Object.keys(args).filter(function (key) { return isNaN(+key); });
    var returnedObject = {};
    keys.forEach(function (key) {
        switch (typeof args[key]) {
            case "boolean":
            case "number":
            case "string":
                returnedObject[key] = args[key];
                break;
            case "object":
                if (Array.isArray(args[key])) {
                    returnedObject[key] =
                        Object.keys(args[key]).filter(function (key) { return isNaN(+key); }).length > 0
                            ? spreadEvent(args[key])
                            : args[key];
                }
                else {
                    returnedObject[key] = args[key];
                }
                break;
        }
    });
    if (returnedObject.groupIndex) {
        returnedObject.groupIndex = Number(returnedObject.groupIndex);
    }
    if (returnedObject.leafId) {
        returnedObject.leafId = Number(returnedObject.leafId);
    }
    if (returnedObject.chainId) {
        returnedObject.chainId = Number(returnedObject.chainId);
    }
    if (returnedObject.destinationChainId) {
        returnedObject.destinationChainId = Number(returnedObject.destinationChainId);
    }
    if (returnedObject.originChainId) {
        returnedObject.originChainId = Number(returnedObject.originChainId);
    }
    if (returnedObject.repaymentChainId) {
        returnedObject.repaymentChainId = Number(returnedObject.repaymentChainId);
    }
    if (returnedObject.l2ChainId) {
        returnedObject.l2ChainId = Number(returnedObject.l2ChainId);
    }
    if (returnedObject.rootBundleId) {
        returnedObject.rootBundleId = Number(returnedObject.rootBundleId);
    }
    if ((0, _1.isDefined)(returnedObject.depositId)) {
        returnedObject.depositId = (0, _1.toBN)(returnedObject.depositId);
    }
    return returnedObject;
}
exports.spreadEvent = spreadEvent;
var eventToLog = function (event) { return (tslib_1.__assign(tslib_1.__assign({}, event), { event: event.event, args: spreadEvent(event.args) })); };
exports.eventToLog = eventToLog;
function paginatedEventQuery(contract, filter, searchConfig, retryCount) {
    if (retryCount === void 0) { retryCount = 0; }
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var events, paginatedRanges, error_1;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    if (!(searchConfig.maxLookBack === 0)) return [3, 2];
                    return [4, contract.queryFilter(filter, searchConfig.from, searchConfig.to)];
                case 1:
                    events = _a.sent();
                    return [2, events.map(exports.eventToLog)];
                case 2:
                    paginatedRanges = getPaginatedBlockRanges(searchConfig);
                    _a.label = 3;
                case 3:
                    _a.trys.push([3, 5, , 10]);
                    return [4, Promise.all(paginatedRanges.map(function (_a) {
                            var fromBlock = _a[0], toBlock = _a[1];
                            return contract.queryFilter(filter, fromBlock, toBlock);
                        }))];
                case 4: return [2, ((_a.sent())
                        .flat()
                        .filter(function (event) { return event.blockNumber >= searchConfig.from && event.blockNumber <= searchConfig.to; })
                        .map(exports.eventToLog))];
                case 5:
                    error_1 = _a.sent();
                    if (!(retryCount < maxRetries)) return [3, 8];
                    return [4, (0, common_1.delay)(retrySleepTime)];
                case 6:
                    _a.sent();
                    return [4, paginatedEventQuery(contract, filter, searchConfig, retryCount + 1)];
                case 7: return [2, _a.sent()];
                case 8: throw error_1;
                case 9: return [3, 10];
                case 10: return [2];
            }
        });
    });
}
exports.paginatedEventQuery = paginatedEventQuery;
function getPaginatedBlockRanges(_a) {
    var from = _a.from, to = _a.to, maxLookBack = _a.maxLookBack;
    var fromBlock = from;
    var toBlock = to;
    var maxBlockLookBack = maxLookBack;
    if (maxBlockLookBack === undefined) {
        return [[fromBlock, toBlock]];
    }
    if (fromBlock > toBlock) {
        return [];
    }
    if (maxBlockLookBack <= 0) {
        throw new Error("Cannot set maxBlockLookBack <= 0");
    }
    var flooredStartBlock = Math.floor(fromBlock / maxBlockLookBack) * maxBlockLookBack;
    var iterations = Math.ceil((toBlock + 1 - flooredStartBlock) / maxBlockLookBack);
    var ranges = [];
    for (var i = 0; i < iterations; i++) {
        var innerFromBlock = flooredStartBlock + maxBlockLookBack * i;
        var innerToBlock = Math.min(innerFromBlock + maxBlockLookBack - 1, toBlock);
        ranges.push([innerFromBlock, innerToBlock]);
    }
    return ranges;
}
exports.getPaginatedBlockRanges = getPaginatedBlockRanges;
function logToSortableEvent(log) {
    return {
        txnIndex: log.transactionIndex,
        txnRef: log.transactionHash,
        logIndex: log.logIndex,
        blockNumber: log.blockNumber,
    };
}
exports.logToSortableEvent = logToSortableEvent;
function spreadEventWithBlockNumber(event) {
    return tslib_1.__assign(tslib_1.__assign({}, spreadEvent(event.args)), logToSortableEvent(event));
}
exports.spreadEventWithBlockNumber = spreadEventWithBlockNumber;
function sortEventsAscending(events) {
    return sortEventsAscendingInPlace(tslib_1.__spreadArray([], events, true));
}
exports.sortEventsAscending = sortEventsAscending;
function sortEventsAscendingInPlace(events) {
    return events.sort(function (ex, ey) {
        return ex.blockNumber === ey.blockNumber ? ex.logIndex - ey.logIndex : ex.blockNumber - ey.blockNumber;
    });
}
exports.sortEventsAscendingInPlace = sortEventsAscendingInPlace;
function sortEventsDescending(events) {
    return sortEventsDescendingInPlace(tslib_1.__spreadArray([], events, true));
}
exports.sortEventsDescending = sortEventsDescending;
function sortEventsDescendingInPlace(events) {
    return events.sort(function (ex, ey) {
        return ex.blockNumber === ey.blockNumber ? ey.logIndex - ex.logIndex : ey.blockNumber - ex.blockNumber;
    });
}
exports.sortEventsDescendingInPlace = sortEventsDescendingInPlace;
function isEventOlder(ex, ey) {
    return ex.blockNumber === ey.blockNumber ? ex.logIndex < ey.logIndex : ex.blockNumber < ey.blockNumber;
}
exports.isEventOlder = isEventOlder;
function getTransactionRefs(events) {
    return tslib_1.__spreadArray([], Array.from(new Set(events.map(function (e) { return e.txnRef; }))), true);
}
exports.getTransactionRefs = getTransactionRefs;
function duplicateEvent(a, b) {
    return a.txnRef === b.txnRef && a.logIndex === b.logIndex;
}
exports.duplicateEvent = duplicateEvent;
//# sourceMappingURL=EventUtils.js.map