import { __spreadArray } from "tslib";
import assert from "assert";
import { utils as ethersUtils } from "ethers";
import { random } from "lodash";
import { isDefined } from "../../utils";
var id = ethersUtils.id, keccak256 = ethersUtils.keccak256, toUtf8Bytes = ethersUtils.toUtf8Bytes;
var eventManagers = {};
var EventManager = /** @class */ (function () {
    function EventManager(blockNumber) {
        if (blockNumber === void 0) { blockNumber = 0; }
        this.blockNumber = blockNumber;
        this.logIndexes = {};
        this.events = [];
        this.minBlockRange = 10;
        this.eventSignatures = {};
    }
    EventManager.prototype.addEventSignatures = function (eventSignatures) {
        var _this = this;
        Object.entries(eventSignatures).forEach(function (_a) {
            var event = _a[0], signature = _a[1];
            if (isDefined(_this.eventSignatures[event])) {
                assert(signature === _this.eventSignatures[event], "Event ".concat(event, " conflict detected."));
            }
            _this.eventSignatures[event] = signature;
        });
    };
    EventManager.prototype.addEvent = function (event) {
        this.events.push(event);
    };
    EventManager.prototype.getEvents = function () {
        var events = this.events;
        this.events = [];
        return events;
    };
    EventManager.prototype.generateEvent = function (inputs) {
        var _a;
        var _b;
        var address = inputs.address, event = inputs.event, topics = inputs.topics, data = inputs.data, args = inputs.args;
        var blockNumber = inputs.blockNumber, transactionIndex = inputs.transactionIndex;
        var eventSignature = "".concat(event, "(").concat(this.eventSignatures[event], ")");
        // Increment the block number by at least 1, by default. The caller may override
        // to force the same block number to be used, but never a previous block number.
        blockNumber !== null && blockNumber !== void 0 ? blockNumber : (blockNumber = random(this.blockNumber + 1, this.blockNumber + this.minBlockRange, false));
        assert(blockNumber >= this.blockNumber, "".concat(blockNumber, " < ").concat(this.blockNumber));
        this.blockNumber = blockNumber;
        transactionIndex !== null && transactionIndex !== void 0 ? transactionIndex : (transactionIndex = random(1, 32, false));
        var _logIndex = "".concat(blockNumber, "-").concat(transactionIndex);
        (_a = (_b = this.logIndexes)[_logIndex]) !== null && _a !== void 0 ? _a : (_b[_logIndex] = 0);
        var generatedEvent = {
            event: event,
            blockNumber: blockNumber,
            transactionIndex: transactionIndex,
            logIndex: this.logIndexes[_logIndex]++,
            transactionHash: id("Across-".concat(event, "-").concat(blockNumber, "-").concat(transactionIndex, "-").concat(random(1, 100000))),
            removed: false,
            address: address,
            data: data !== null && data !== void 0 ? data : id("Across-random-txndata-".concat(random(1, 100000))),
            topics: __spreadArray([keccak256(toUtf8Bytes(eventSignature))], topics, true),
            args: args,
            blockHash: id("Across-blockHash-".concat(random(1, 100000))),
        };
        this.addEvent(generatedEvent);
        return generatedEvent;
    };
    return EventManager;
}());
export { EventManager };
/**
 * @description Retrieve an instance of the EventManager for a specific chain, or instantiate a new one.
 * @param chainId Chain ID to retrieve EventManager for.
 * @param eventSignatures Event Signatures to append to EventManager instance.
 * @param Initial blockNumber to use if a new EventManager is instantiated.
 * @returns EventManager instance for chain ID.
 */
export function getEventManager(chainId, eventSignatures, blockNumber) {
    if (!isDefined(eventManagers[chainId])) {
        eventManagers[chainId] = new EventManager(blockNumber);
    }
    var eventManager = eventManagers[chainId];
    if (isDefined(eventSignatures)) {
        eventManager.addEventSignatures(eventSignatures);
    }
    return eventManager;
}
//# sourceMappingURL=MockEvents.js.map