"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const es6_promisify_1 = require("es6-promisify");
const loggingService_1 = require("./loggingService");
const pubSubEventService_1 = require("./pubSubEventService");
const utils_1 = require("./utils");
/**
 * Watch for changes in the default account.
 *
 * For more information, see [Account Changes](/Configuration.md#accountchanges).
 */
class AccountService {
    /**
     * Initializes the system that watches for default account changes.
     *
     * `initiateAccountWatch` is called automatically by Arc.js when you pass `true`
     * for `watchForAccountChanges` to `InitializeArcJs`.  You may also call it manually yourself.
     *
     * Then you may request to be notified whenever the current account changes by calling
     * [AccountService.subscribeToAccountChanges](/arc.js/api/classes/AccountService#subscribeToAccountChanges)
     */
    static initiateAccountWatch() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (AccountService.accountChangedTimerId) {
                return;
            }
            loggingService_1.LoggingService.info("Initiating account watch");
            if (!AccountService.currentAccount) {
                try {
                    AccountService.currentAccount = yield utils_1.Utils.getDefaultAccount();
                }
                catch (_a) {
                    AccountService.currentAccount = undefined;
                }
            }
            AccountService.accountChangedTimerId = setInterval(() => tslib_1.__awaiter(this, void 0, void 0, function* () {
                if (AccountService.accountChangedLock) {
                    return; // prevent reentrance
                }
                AccountService.accountChangedLock = true;
                let currentAccount = AccountService.currentAccount;
                try {
                    currentAccount = yield utils_1.Utils.getDefaultAccount();
                }
                catch (_b) {
                    currentAccount = undefined;
                }
                if (currentAccount !== AccountService.currentAccount) {
                    AccountService.currentAccount = currentAccount;
                    loggingService_1.LoggingService.info(`Account watch: account changed: ${currentAccount}`);
                    pubSubEventService_1.PubSubEventService.publish(AccountService.AccountChangedEventTopic, currentAccount);
                }
                AccountService.accountChangedLock = false;
            }), 1000);
        });
    }
    /**
     * Initializes the system that watches for blockchain network id changes.
     *
     * `initiateNetworkWatch` is called automatically by Arc.js when you pass `true`
     * for `watchForNetworkChanges` to `InitializeArcJs`.  You may also call it manually yourself.
     *
     * Then you may request to be notified whenever the current account changes by calling
     * [AccountService.subscribeToNetworkChanges](/arc.js/api/classes/AccountService#subscribeToNetworkChanges)
     *
     * When the network is found to have changed you should call `InitializeArcJs` so Arc.js will set
     * itself up with the new network and return to you a new `Web3` object.
     */
    static initiateNetworkWatch() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (AccountService.networkChangedTimerId) {
                return;
            }
            loggingService_1.LoggingService.info("Initiating network watch");
            if (!AccountService.currentNetworkId) {
                try {
                    AccountService.currentNetworkId = yield AccountService.getNetworkId();
                }
                catch (_a) {
                    AccountService.currentNetworkId = undefined;
                }
            }
            AccountService.networkChangedTimerId = setInterval(() => tslib_1.__awaiter(this, void 0, void 0, function* () {
                if (AccountService.networkChangedLock) {
                    return; // prevent reentrance
                }
                AccountService.networkChangedLock = true;
                let currentNetworkId = AccountService.currentNetworkId;
                try {
                    currentNetworkId = yield AccountService.getNetworkId();
                }
                catch (_b) {
                    currentNetworkId = undefined;
                }
                if (currentNetworkId !== AccountService.currentNetworkId) {
                    AccountService.currentNetworkId = currentNetworkId;
                    loggingService_1.LoggingService.info(`Network watch: network changed: ${currentNetworkId}`);
                    pubSubEventService_1.PubSubEventService.publish(AccountService.NetworkChangedEventTopic, currentNetworkId);
                }
                AccountService.networkChangedLock = false;
            }), 1000);
        });
    }
    /**
     * Turn off the system that watches for default account changes.
     */
    static endAccountWatch() {
        if (AccountService.accountChangedTimerId) {
            clearInterval(AccountService.accountChangedTimerId);
            AccountService.accountChangedTimerId = undefined;
        }
    }
    /**
     * Turn off the system that watches for default account changes.
     */
    static endNetworkWatch() {
        if (AccountService.networkChangedTimerId) {
            clearInterval(AccountService.networkChangedTimerId);
            AccountService.networkChangedTimerId = undefined;
        }
    }
    /**
     * Subscribe to be notified whenever the current account changes, like this:
     *
     * ```typescript
     * AccountService.subscribeToAccountChanges((account: Address): void => { ... });
     * ```
     * @param callback
     * @returns A subscription to the event.  Unsubscribe by calling `[theSubscription].unsubscribe()`.
     */
    static subscribeToAccountChanges(callback) {
        return pubSubEventService_1.PubSubEventService.subscribe(AccountService.AccountChangedEventTopic, (topic, address) => callback(address));
    }
    /**
     * Subscribe to be notified whenever the current network changes, like this:
     *
     * ```typescript
     * AccountService.subscribeToAccountChanges((networkId: number): void => { ... });
     * ```
     * @param callback
     * @returns A subscription to the event.  Unsubscribe by calling `[theSubscription].unsubscribe()`.
     */
    static subscribeToNetworkChanges(callback) {
        return pubSubEventService_1.PubSubEventService.subscribe(AccountService.NetworkChangedEventTopic, (topic, networkId) => callback(networkId));
    }
    static getNetworkId() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const web3 = yield utils_1.Utils.getWeb3();
            return web3 ?
                Number.parseInt(yield es6_promisify_1.promisify(web3.version.getNetwork)(), 10) : undefined;
        });
    }
}
AccountService.AccountChangedEventTopic = "AccountService.account.changed";
AccountService.NetworkChangedEventTopic = "AccountService.network.changed";
AccountService.accountChangedLock = false;
AccountService.networkChangedLock = false;
exports.AccountService = AccountService;
//# sourceMappingURL=accountService.js.map