import { __awaiter, __extends, __generator } from "tslib";
import { randomAddress, assign, bnZero, toAddressType, EvmAddress, isDefined } from "../../utils";
import { HubPoolClient } from "../HubPoolClient";
import { getEventManager } from "./MockEvents";
import { ZERO_ADDRESS } from "../../constants";
var emptyRootBundle = {
    poolRebalanceRoot: "",
    relayerRefundRoot: "",
    slowRelayRoot: "",
    proposer: EvmAddress.from(ZERO_ADDRESS),
    unclaimedPoolRebalanceLeafCount: 0,
    challengePeriodEndTimestamp: 0,
    bundleEvaluationBlockNumbers: [],
    proposalBlockNumber: undefined,
};
var MockHubPoolClient = /** @class */ (function (_super) {
    __extends(MockHubPoolClient, _super);
    function MockHubPoolClient(logger, hubPool, configStoreClient, deploymentBlock, chainId) {
        if (deploymentBlock === void 0) { deploymentBlock = 0; }
        if (chainId === void 0) { chainId = 1; }
        var _this = _super.call(this, logger, hubPool, configStoreClient, deploymentBlock, chainId) || this;
        _this.rootBundleProposal = emptyRootBundle;
        _this.realizedLpFeePct = bnZero;
        _this.realizedLpFeePctOverride = false;
        _this.l1TokensMock = []; // L1Tokens and their associated info.
        _this.spokePoolTokens = {};
        _this.eventSignatures = {
            SetEnableDepositRoute: "uint256,uint256,address,bool",
            SetPoolRebalanceRoute: "uint256,address,address",
            ProposeRootBundle: "uint32,uint8,uint256[],bytes32,bytes32,bytes32,address",
            RootBundleExecuted: "uint256,uint256,uint256,address[],uint256[],int256[],int256[],address",
        };
        _this.eventManager = getEventManager(chainId, _this.eventSignatures, deploymentBlock);
        return _this;
    }
    MockHubPoolClient.prototype.setDefaultRealizedLpFeePct = function (fee) {
        this.realizedLpFeePct = fee;
        this.realizedLpFeePctOverride = true;
    };
    MockHubPoolClient.prototype.clearDefaultRealizedLpFeePct = function () {
        this.realizedLpFeePctOverride = false;
    };
    MockHubPoolClient.prototype.computeRealizedLpFeePct = function (deposit) {
        return __awaiter(this, void 0, void 0, function () {
            var _a, realizedLpFeePct, realizedLpFeePctOverride, _b;
            return __generator(this, function (_c) {
                switch (_c.label) {
                    case 0:
                        _a = this, realizedLpFeePct = _a.realizedLpFeePct, realizedLpFeePctOverride = _a.realizedLpFeePctOverride;
                        if (!realizedLpFeePctOverride) return [3 /*break*/, 1];
                        _b = { realizedLpFeePct: realizedLpFeePct, quoteBlock: 0 };
                        return [3 /*break*/, 3];
                    case 1: return [4 /*yield*/, _super.prototype.computeRealizedLpFeePct.call(this, deposit)];
                    case 2:
                        _b = _c.sent();
                        _c.label = 3;
                    case 3: return [2 /*return*/, _b];
                }
            });
        });
    };
    MockHubPoolClient.prototype.batchComputeRealizedLpFeePct = function (_deposits) {
        return __awaiter(this, void 0, void 0, function () {
            var _a, realizedLpFeePct, realizedLpFeePctOverride, _b;
            return __generator(this, function (_c) {
                switch (_c.label) {
                    case 0:
                        _a = this, realizedLpFeePct = _a.realizedLpFeePct, realizedLpFeePctOverride = _a.realizedLpFeePctOverride;
                        if (!realizedLpFeePctOverride) return [3 /*break*/, 1];
                        _b = _deposits.map(function () {
                            return { realizedLpFeePct: realizedLpFeePct, quoteBlock: 0 };
                        });
                        return [3 /*break*/, 3];
                    case 1: return [4 /*yield*/, _super.prototype.batchComputeRealizedLpFeePct.call(this, _deposits)];
                    case 2:
                        _b = _c.sent();
                        _c.label = 3;
                    case 3: return [2 /*return*/, _b];
                }
            });
        });
    };
    MockHubPoolClient.prototype.setCrossChainContracts = function (chainId, contract, blockNumber) {
        if (blockNumber === void 0) { blockNumber = 0; }
        assign(this.crossChainContracts, [chainId], [
            {
                spokePool: toAddressType(contract, chainId),
                blockNumber: blockNumber,
                logIndex: 0,
                l2ChainId: chainId,
                txnIndex: 0,
                txnRef: "",
            },
        ]);
    };
    MockHubPoolClient.prototype.setLatestBlockNumber = function (blockNumber) {
        this.latestHeightSearched = blockNumber;
    };
    MockHubPoolClient.prototype.addL1Token = function (l1Token) {
        this.l1TokensMock.push(l1Token);
    };
    MockHubPoolClient.prototype.getL1Tokens = function () {
        return this.l1TokensMock;
    };
    MockHubPoolClient.prototype.setTokenMapping = function (l1Token, chainId, l2Token) {
        var _a;
        var _b;
        (_a = (_b = this.spokePoolTokens)[l1Token]) !== null && _a !== void 0 ? _a : (_b[l1Token] = {});
        this.spokePoolTokens[l1Token][chainId] = toAddressType(l2Token, chainId);
    };
    MockHubPoolClient.prototype.l2TokenEnabledForL1TokenAtBlock = function (l1Token, destinationChainId, hubBlockNumber) {
        var _a;
        if ((_a = this.spokePoolTokens[l1Token.toEvmAddress()]) === null || _a === void 0 ? void 0 : _a[destinationChainId]) {
            return true;
        }
        else {
            return _super.prototype.l2TokenEnabledForL1TokenAtBlock.call(this, l1Token, destinationChainId, hubBlockNumber);
        }
    };
    MockHubPoolClient.prototype.l2TokenHasPoolRebalanceRoute = function (l2Token, chainId, hubPoolBlock) {
        var _this = this;
        var l1Token = Object.keys(this.spokePoolTokens).find(function (l1Token) { var _a, _b; return (_b = (_a = _this.spokePoolTokens[l1Token]) === null || _a === void 0 ? void 0 : _a[chainId]) === null || _b === void 0 ? void 0 : _b.eq(l2Token); });
        if (!l1Token) {
            return _super.prototype.l2TokenHasPoolRebalanceRoute.call(this, l2Token, chainId, hubPoolBlock);
        }
        else
            return true;
    };
    MockHubPoolClient.prototype.deleteTokenMapping = function (l1Token, chainId) {
        var _a;
        (_a = this.spokePoolTokens[l1Token]) === null || _a === void 0 ? true : delete _a[chainId];
    };
    MockHubPoolClient.prototype.getL1TokenForL2TokenAtBlock = function (l2Token, chainId, blockNumber) {
        var _this = this;
        var l1Token = Object.keys(this.spokePoolTokens).find(function (l1Token) { var _a; return (_a = _this.spokePoolTokens[l1Token]) === null || _a === void 0 ? void 0 : _a[chainId].eq(l2Token); });
        if (isDefined(l1Token)) {
            return EvmAddress.from(l1Token);
        }
        else {
            return _super.prototype.getL1TokenForL2TokenAtBlock.call(this, l2Token, chainId, blockNumber);
        }
    };
    MockHubPoolClient.prototype.getL2TokenForL1TokenAtBlock = function (l1Token, chainId, blockNumber) {
        var _a;
        var l2Token = (_a = this.spokePoolTokens[l1Token.toEvmAddress()]) === null || _a === void 0 ? void 0 : _a[chainId];
        return l2Token !== null && l2Token !== void 0 ? l2Token : _super.prototype.getL2TokenForL1TokenAtBlock.call(this, l1Token, chainId, blockNumber);
    };
    MockHubPoolClient.prototype.getTokenInfoForL1Token = function (l1Token) {
        return this.l1TokensMock.find(function (token) { return token.address.eq(l1Token); });
    };
    MockHubPoolClient.prototype._update = function (eventNames) {
        // Generate new "on chain" responses.
        var latestBlockSearched = this.eventManager.blockNumber;
        var currentTime = Math.floor(Date.now() / 1000);
        // Ensure an array for every requested event exists, in the requested order.
        // All requested event types must be populated in the array (even if empty).
        var _events = eventNames.map(function () { return []; });
        this.eventManager
            .getEvents()
            .flat()
            .forEach(function (event) {
            var idx = eventNames.indexOf(event.event);
            if (idx !== -1) {
                _events[idx].push(event);
            }
        });
        // Transform 2d-events array into a record.
        var events = Object.fromEntries(eventNames.map(function (eventName, idx) { return [eventName, _events[idx]]; }));
        return Promise.resolve({
            success: true,
            currentTime: currentTime,
            latestBlockSearched: latestBlockSearched,
            pendingRootBundleProposal: this.rootBundleProposal,
            events: events,
            searchEndBlock: this.eventSearchConfig.to || latestBlockSearched,
        });
    };
    MockHubPoolClient.prototype.setCrossChainContractsEvent = function (l2ChainId, adapter, spokePool, overrides) {
        if (overrides === void 0) { overrides = {}; }
        var event = "CrossChainContractsSet";
        var topics = [];
        var args = {
            l2ChainId: l2ChainId,
            adapter: adapter,
            spokePool: spokePool,
        };
        return this.eventManager.generateEvent({
            event: event,
            address: this.hubPool.address,
            topics: topics.map(function (topic) { return topic.toString(); }),
            args: args,
            blockNumber: overrides.blockNumber,
        });
    };
    MockHubPoolClient.prototype.setPoolRebalanceRoute = function (destinationChainId, l1Token, destinationToken, overrides) {
        if (overrides === void 0) { overrides = {}; }
        var event = "SetPoolRebalanceRoute";
        var topics = [destinationChainId, l1Token, destinationToken];
        var args = {
            destinationChainId: destinationChainId,
            l1Token: l1Token,
            destinationToken: destinationToken,
        };
        return this.eventManager.generateEvent({
            event: event,
            address: this.hubPool.address,
            topics: topics.map(function (topic) { return topic.toString(); }),
            args: args,
            blockNumber: overrides.blockNumber,
        });
    };
    MockHubPoolClient.prototype.proposeRootBundle = function (challengePeriodEndTimestamp, poolRebalanceLeafCount, bundleEvaluationBlockNumbers, poolRebalanceRoot, relayerRefundRoot, slowRelayRoot, proposer, overrides) {
        if (overrides === void 0) { overrides = {}; }
        var event = "ProposeRootBundle";
        poolRebalanceRoot !== null && poolRebalanceRoot !== void 0 ? poolRebalanceRoot : (poolRebalanceRoot = "XX");
        relayerRefundRoot !== null && relayerRefundRoot !== void 0 ? relayerRefundRoot : (relayerRefundRoot = "XX");
        slowRelayRoot !== null && slowRelayRoot !== void 0 ? slowRelayRoot : (slowRelayRoot = "XX");
        proposer !== null && proposer !== void 0 ? proposer : (proposer = randomAddress());
        var topics = [poolRebalanceRoot, relayerRefundRoot, proposer];
        var args = {
            challengePeriodEndTimestamp: challengePeriodEndTimestamp,
            poolRebalanceLeafCount: poolRebalanceLeafCount,
            bundleEvaluationBlockNumbers: bundleEvaluationBlockNumbers,
            poolRebalanceRoot: poolRebalanceRoot,
            relayerRefundRoot: relayerRefundRoot,
            slowRelayRoot: slowRelayRoot,
            proposer: proposer,
        };
        return this.eventManager.generateEvent({
            event: event,
            address: this.hubPool.address,
            topics: topics.map(function (topic) { return topic.toString(); }),
            args: args,
            blockNumber: overrides.blockNumber,
        });
    };
    MockHubPoolClient.prototype.executeRootBundle = function (groupIndex, leafId, chainId, l1Tokens, bundleLpFees, netSendAmounts, runningBalances, caller, overrides) {
        if (overrides === void 0) { overrides = {}; }
        var event = "RootBundleExecuted";
        caller !== null && caller !== void 0 ? caller : (caller = randomAddress());
        var topics = [leafId, chainId, caller];
        var args = {
            groupIndex: groupIndex,
            leafId: leafId,
            chainId: chainId,
            l1Tokens: l1Tokens,
            bundleLpFees: bundleLpFees,
            netSendAmounts: netSendAmounts,
            runningBalances: runningBalances,
            caller: caller,
        };
        return this.eventManager.generateEvent({
            event: event,
            address: this.hubPool.address,
            topics: topics.map(function (topic) { return topic.toString(); }),
            args: args,
            blockNumber: overrides.blockNumber,
        });
    };
    return MockHubPoolClient;
}(HubPoolClient));
export { MockHubPoolClient };
//# sourceMappingURL=MockHubPoolClient.js.map