import { CONNECTOR_STATUS, WalletInitializationError, CONNECTOR_EVENTS, ANALYTICS_INTEGRATION_TYPE } from '@web3auth/no-modal';
import { createContext, useState, useMemo, useCallback, useEffect, createElement } from 'react';
import { Web3Auth } from '../../modalManager.js';

const Web3AuthInnerContext = /*#__PURE__*/createContext(null);
function Web3AuthInnerProvider(params) {
  const {
    children,
    config,
    initialState
  } = params;
  const {
    web3AuthOptions
  } = config;
  const [chainId, setChainId] = useState(null);
  const [chainNamespace, setChainNamespace] = useState(null);
  const [isInitializing, setIsInitializing] = useState(false);
  const [initError, setInitError] = useState(null);
  const [provider, setProvider] = useState(null);
  const [isInitialized, setIsInitialized] = useState(false);
  const [isMFAEnabled, setIsMFAEnabled] = useState(false);
  const web3Auth = useMemo(() => {
    setProvider(null);
    return new Web3Auth(web3AuthOptions, initialState);
  }, [web3AuthOptions, initialState]);
  const [isConnected, setIsConnected] = useState(web3Auth.status === CONNECTOR_STATUS.CONNECTED);
  const [status, setStatus] = useState(web3Auth.status);
  const getPlugin = useCallback(name => {
    if (!web3Auth) throw WalletInitializationError.notReady();
    return web3Auth.getPlugin(name);
  }, [web3Auth]);
  useEffect(() => {
    const controller = new AbortController();
    async function init() {
      try {
        var _web3Auth$currentChai;
        setInitError(null);
        setIsInitializing(true);
        web3Auth.setAnalyticsProperties({
          integration_type: ANALYTICS_INTEGRATION_TYPE.REACT_HOOKS
        });
        await web3Auth.init({
          signal: controller.signal
        });
        setChainId(web3Auth.currentChainId);
        setChainNamespace((_web3Auth$currentChai = web3Auth.currentChain) === null || _web3Auth$currentChai === void 0 ? void 0 : _web3Auth$currentChai.chainNamespace);
      } catch (error) {
        setInitError(error);
      } finally {
        setIsInitializing(false);
      }
    }
    if (web3Auth) init();
    return () => {
      controller.abort();
    };
  }, [web3Auth, config]);
  useEffect(() => {
    const handleChainChange = async chainId => {
      var _web3Auth$currentChai2;
      setChainId(chainId);
      setChainNamespace(web3Auth === null || web3Auth === void 0 || (_web3Auth$currentChai2 = web3Auth.currentChain) === null || _web3Auth$currentChai2 === void 0 ? void 0 : _web3Auth$currentChai2.chainNamespace);
    };
    if (provider) {
      provider.on("chainChanged", handleChainChange);
      return () => {
        provider.off("chainChanged", handleChainChange);
      };
    }
  }, [web3Auth, provider]);
  useEffect(() => {
    const notReadyListener = () => setStatus(web3Auth.status);
    const readyListener = () => {
      setStatus(web3Auth.status);
      setIsInitialized(true);
    };
    const connectedListener = data => {
      setStatus(web3Auth.status);
      // we do this because of rehydration issues. status connected is fired first but web3auth sdk is not ready yet.
      if (web3Auth.status === CONNECTOR_STATUS.CONNECTED) {
        setIsInitialized(true);
        setIsConnected(true);
        setProvider(data.provider);
      }
    };
    const disconnectedListener = () => {
      setStatus(web3Auth.status);
      setIsConnected(false);
      setProvider(null);
    };
    const connectingListener = () => {
      setStatus(web3Auth.status);
    };
    const errorListener = () => {
      setStatus(web3Auth.status);
    };
    const rehydrationErrorListener = () => {
      setStatus(web3Auth.status);
      setIsConnected(false);
      setProvider(null);
    };
    const mfaEnabledListener = isMFAEnabled => {
      if (typeof isMFAEnabled === "boolean") setIsMFAEnabled(isMFAEnabled);
    };
    if (web3Auth) {
      // web3Auth is initialized here.
      setStatus(web3Auth.status);
      web3Auth.on(CONNECTOR_EVENTS.NOT_READY, notReadyListener);
      web3Auth.on(CONNECTOR_EVENTS.READY, readyListener);
      web3Auth.on(CONNECTOR_EVENTS.CONNECTED, connectedListener);
      web3Auth.on(CONNECTOR_EVENTS.DISCONNECTED, disconnectedListener);
      web3Auth.on(CONNECTOR_EVENTS.CONNECTING, connectingListener);
      web3Auth.on(CONNECTOR_EVENTS.ERRORED, errorListener);
      web3Auth.on(CONNECTOR_EVENTS.REHYDRATION_ERROR, rehydrationErrorListener);
      web3Auth.on(CONNECTOR_EVENTS.MFA_ENABLED, mfaEnabledListener);
    }
    return () => {
      if (web3Auth) {
        web3Auth.off(CONNECTOR_EVENTS.NOT_READY, notReadyListener);
        web3Auth.off(CONNECTOR_EVENTS.READY, readyListener);
        web3Auth.off(CONNECTOR_EVENTS.CONNECTED, connectedListener);
        web3Auth.off(CONNECTOR_EVENTS.DISCONNECTED, disconnectedListener);
        web3Auth.off(CONNECTOR_EVENTS.CONNECTING, connectingListener);
        web3Auth.off(CONNECTOR_EVENTS.ERRORED, errorListener);
        web3Auth.off(CONNECTOR_EVENTS.REHYDRATION_ERROR, rehydrationErrorListener);
        web3Auth.off(CONNECTOR_EVENTS.MFA_ENABLED, mfaEnabledListener);
        web3Auth.cleanup();
      }
    };
  }, [web3Auth]);
  const value = useMemo(() => {
    return {
      web3Auth,
      isConnected,
      isInitialized,
      provider,
      status,
      isInitializing,
      initError,
      isMFAEnabled,
      chainId,
      chainNamespace,
      getPlugin,
      setIsMFAEnabled
    };
  }, [web3Auth, isConnected, isMFAEnabled, setIsMFAEnabled, isInitialized, provider, status, getPlugin, isInitializing, initError, chainId, chainNamespace]);
  return /*#__PURE__*/createElement(Web3AuthInnerContext.Provider, {
    value
  }, children);
}

export { Web3AuthInnerContext, Web3AuthInnerProvider };
