import assert from "assert";
import { ethers } from "ethers";
import { getCurrentTime, utf8ToHex, spreadEventWithBlockNumber } from "../../utils";
import { AcrossConfigStoreClient, DEFAULT_CONFIG_STORE_VERSION, GLOBAL_CONFIG_STORE_KEYS, } from "../AcrossConfigStoreClient";
import { CHAIN_IDs } from "../../constants";
import { EventManager } from "./MockEvents";
export class MockConfigStoreClient extends AcrossConfigStoreClient {
    configStoreVersion = DEFAULT_CONFIG_STORE_VERSION;
    eventManager;
    availableChainIdsOverride;
    // Event signatures. Not strictly required, but they make generated events more recognisable.
    eventSignatures = {
        OwnershipTransferred: "address,address",
        UpdatedGlobalConfig: "bytes32,string",
        UpdatedTokenConfig: "address,string",
    };
    constructor(logger, configStore, eventSearchConfig = { from: 0, maxLookBack: 0 }, configStoreVersion, chainId = CHAIN_IDs.MAINNET, mockUpdate = false, availableChainIdsOverride, opts = {}) {
        super(logger, configStore, eventSearchConfig, configStoreVersion);
        this.chainId = chainId;
        if (mockUpdate) {
            this.eventManager = opts.eventManager ?? new EventManager();
            this.eventManager.addEventSignatures(this.eventSignatures);
            this.updateGlobalConfig(GLOBAL_CONFIG_STORE_KEYS.CHAIN_ID_INDICES, JSON.stringify(availableChainIdsOverride), {
                blockNumber: this.eventManager.blockNumber,
            });
        }
        else {
            this.eventManager = null;
        }
    }
    setAvailableChains(chainIds) {
        this.availableChainIdsOverride = chainIds;
    }
    getChainIdIndicesForBlock(block) {
        return this.availableChainIdsOverride ?? super.getChainIdIndicesForBlock(block);
    }
    getConfigStoreVersionForBlock(_blockNumber) {
        return this.configStoreVersion === DEFAULT_CONFIG_STORE_VERSION
            ? super.getConfigStoreVersionForBlock(_blockNumber)
            : this.configStoreVersion;
    }
    setConfigStoreVersion(version) {
        this.configStoreVersion = version;
    }
    _update() {
        // Backwards compatibility for pre-existing MockConfigStoreClient users.
        if (this.eventManager === null) {
            return super._update();
        }
        const eventNames = ["UpdatedGlobalConfig", "UpdatedTokenConfig"];
        const latestBlockSearched = this.eventManager.blockNumber;
        // 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).
        const globalConfigUpdateTimes = [];
        const _events = eventNames.map(() => []);
        for (const event of this.eventManager.getEvents().flat()) {
            const idx = eventNames.indexOf(event.event);
            if (idx !== -1) {
                _events[idx].push(event);
            }
            if (event.event === "UpdatedGlobalConfig") {
                globalConfigUpdateTimes.push(getCurrentTime());
            }
        }
        // Transform 2d-events array into a record.
        const events = Object.fromEntries(eventNames.map((eventName, idx) => [eventName, _events[idx]]));
        return Promise.resolve({
            success: true,
            chainId: this.chainId,
            searchEndBlock: this.eventSearchConfig.to || latestBlockSearched,
            events: {
                updatedGlobalConfigEvents: events["UpdatedGlobalConfig"].map(spreadEventWithBlockNumber),
                globalConfigUpdateTimes,
                updatedTokenConfigEvents: events["UpdatedTokenConfig"].map(spreadEventWithBlockNumber),
            },
        });
    }
    updateGlobalConfig(key, value, overrides = {}) {
        return this.generateConfig("UpdatedGlobalConfig", utf8ToHex(key), value, overrides);
    }
    updateTokenConfig(key, value, overrides = {}) {
        // Verify that the key is a valid address
        if (ethers.utils.isAddress(key) === false) {
            throw new Error(`Invalid address: ${key}`);
        }
        return this.generateConfig("UpdatedTokenConfig", key, value, overrides);
    }
    generateConfig(event, key, value, overrides = {}) {
        assert(this.eventManager !== null);
        const topics = [key, value];
        const args = { key, value };
        return this.eventManager.generateEvent({
            event,
            address: this.configStore.address,
            topics: topics.map((topic) => topic.toString()),
            args,
            blockNumber: overrides.blockNumber,
        });
    }
}
//# sourceMappingURL=MockConfigStoreClient.js.map