var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
    if (kind === "m") throw new TypeError("Private method is not writable");
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
    return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
    return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _Detector_name, _Detector_isExtension, _Detector_providers, _Detector_nextProviderId;
import { SupportedChains, getSpec } from "./specs/index.js";
/**
 * Detector is an API for providing an instance of the PolkadotJS API configured
 * to use a WASM-based light client.  It takes care of detecting whether the
 * user has the substrate connect browser extension installed or not and
 * configures the PolkadotJS API appropriately; falling back to a provider
 * which instantiates the WASM light client in the page when the extension is
 * not available.
 *
 * @example
 *
 * ```
 * import { Detector } from '@substrate/connect';
 *
 * // Create a new UApp with a unique name
 * const app = new Detector('burnr-wallet');
 * const westend = await app.connect('westend');
 * const kusama = await app.connect('kusama');
 *
 * await westend.rpc.chain.subscribeNewHeads((lastHeader) => {
 *   console.log(lastHeader.hash);
 * );
 * await kusama.rpc.chain.subscribeNewHeads((lastHeader) => {
 *   console.log(lastHeader.hash);
 * });
 *
 * // Interact with westend and kusama APIs ...
 *
 * await westend.disconnect();
 * await kusama.disconnect();
 * ```
 */
export class Detector {
    /**
     * @param name - the name of your app.
     *
     * @remarks
     *
     * You should make a best effort to make your app name unique to avoid
     * confusion for users in the extension user interface
     */
    constructor(name) {
        _Detector_name.set(this, void 0);
        _Detector_isExtension.set(this, void 0);
        _Detector_providers.set(this, {});
        _Detector_nextProviderId.set(this, void 0);
        /**
         * Detects and returns an appropriate PolkadotJS provider depending on whether the user has the substrate connect extension installed
         *
         * @param providerId - anId that uniquely identifies the provider in the context of this instance of the Detector
         * @param chain - either a string with the spec of the chain or the name of a supported chain ({@link SupportedChains})
         * @param parachainSpec - optional param of the parachain chainSpecs to connect to
         * @returns a provider will be used in a ApiPromise create for PolkadotJS API
         *
         * @internal
         *
         * @remarks
         * This is used internally for advanced PolkadotJS use cases and is not supported.  Use {@link connect} instead.
         */
        this.internalProvider = async (providerId, chain, parachainSpec) => {
            if (chain.length === 0) {
                throw new Error(`No known Chain was detected and no chainSpec was provided. Either give a known chain name ('${Object.keys(SupportedChains).join("', '")}') or provide valid chainSpecs.`);
            }
            const chainSpecPromise = SupportedChains[chain]
                ? getSpec(chain)
                : Promise.resolve(chain);
            if (__classPrivateFieldGet(this, _Detector_isExtension, "f")) {
                const [{ ExtensionProvider }, chainSpec] = await Promise.all([
                    import("./ExtensionProvider/ExtensionProvider.js"),
                    chainSpecPromise,
                ]);
                return new ExtensionProvider(__classPrivateFieldGet(this, _Detector_name, "f"), providerId, chainSpec, parachainSpec);
            }
            const [{ SmoldotProvider }, chainSpec] = await Promise.all([
                import("./SmoldotProvider/SmoldotProvider.js"),
                chainSpecPromise,
            ]);
            return new SmoldotProvider(chainSpec, parachainSpec);
        };
        __classPrivateFieldSet(this, _Detector_isExtension, !!document.getElementById("substrateExtension"), "f");
        __classPrivateFieldSet(this, _Detector_name, name, "f");
        __classPrivateFieldSet(this, _Detector_nextProviderId, 1, "f");
    }
    /**
     * name is the name of the app. This is used by the extension to identify
     * your app in the user interface
     */
    get name() {
        return __classPrivateFieldGet(this, _Detector_name, "f");
    }
    /**
     * Returns `true` if the user has the extension installed otherwise false
     * @remarks
     * You should check this if you wish to show UI to encourage users to download and install the extension or if you wish your app only to work with the extension installed.
     */
    hasExtension() {
        return __classPrivateFieldGet(this, _Detector_isExtension, "f");
    }
    async connect(chain, parachainSpec, options) {
        var _a;
        var _b;
        const id = (__classPrivateFieldSet(this, _Detector_nextProviderId, (_b = +__classPrivateFieldGet(this, _Detector_nextProviderId, "f")) + 1, "f"), _b);
        const spec = (_a = SupportedChains[chain]) !== null && _a !== void 0 ? _a : chain;
        const [provider, { ApiPromise }] = await Promise.all([
            this.internalProvider(id, spec, parachainSpec),
            import("@polkadot/api"),
        ]);
        __classPrivateFieldGet(this, _Detector_providers, "f")[id] = provider;
        const originalDisconnect = provider.disconnect.bind(provider);
        provider.disconnect = () => {
            delete __classPrivateFieldGet(this, _Detector_providers, "f")[id];
            return originalDisconnect();
        };
        provider.connect().catch(console.error);
        return await ApiPromise.create(Object.assign(options !== null && options !== void 0 ? options : {}, { provider }));
    }
    provider(chain, parachainSpec) {
        var _a;
        return this.internalProvider((__classPrivateFieldSet(this, _Detector_nextProviderId, (_a = +__classPrivateFieldGet(this, _Detector_nextProviderId, "f")) + 1, "f"), _a), chain, parachainSpec);
    }
}
_Detector_name = new WeakMap(), _Detector_isExtension = new WeakMap(), _Detector_providers = new WeakMap(), _Detector_nextProviderId = new WeakMap();
//# sourceMappingURL=Detector.js.map