import _objectSpread from '@babel/runtime/helpers/objectSpread2';
import { WALLET_CONNECTORS, ANALYTICS_EVENTS, log } from '@web3auth/no-modal';
import { useContext, useState, useMemo } from 'react';
import { CONNECT_WALLET_PAGES } from '../../constants.js';
import { AnalyticsContext } from '../../context/AnalyticsContext.js';
import { RootContext } from '../../context/RootContext.js';
import ConnectWalletChainFilter from './ConnectWalletChainFilter/ConnectWalletChainFilter.js';
import ConnectWalletHeader from './ConnectWalletHeader/ConnectWalletHeader.js';
import ConnectWalletList from './ConnectWalletList/ConnectWalletList.js';
import ConnectWalletQrCode from './ConnectWalletQrCode/ConnectWalletQrCode.js';
import ConnectWalletSearch from './ConnectWalletSearch/ConnectWalletSearch.js';
import { jsxs, jsx } from 'react/jsx-runtime';

function ConnectWallet(props) {
  var _selectedButton$walle;
  const {
    isDark,
    config,
    walletConnectUri,
    metamaskConnectUri,
    walletRegistry,
    allExternalButtons,
    customConnectorButtons,
    connectorVisibilityMap,
    deviceDetails,
    buttonRadius = "pill",
    chainNamespace,
    isExternalWalletModeOnly,
    onBackClick,
    handleExternalWalletClick,
    handleWalletDetailsHeight
  } = props;
  const {
    bodyState,
    setBodyState
  } = useContext(RootContext);
  const {
    analytics
  } = useContext(AnalyticsContext);
  const [currentPage, setCurrentPage] = useState(CONNECT_WALLET_PAGES.CONNECT_WALLET);
  const [selectedWallet, setSelectedWallet] = useState(false);
  const [isLoading] = useState(false);
  const [selectedButton, setSelectedButton] = useState(null);
  const [walletSearch, setWalletSearch] = useState("");
  const [selectedChain, setSelectedChain] = useState("all");
  const [isShowAllWallets, setIsShowAllWallets] = useState(false);
  const handleBack = () => {
    if (!selectedWallet && currentPage === CONNECT_WALLET_PAGES.CONNECT_WALLET && onBackClick) {
      onBackClick(false);
      return;
    }
    if (selectedWallet) {
      setCurrentPage(CONNECT_WALLET_PAGES.CONNECT_WALLET);
      setSelectedWallet(false);
      handleWalletDetailsHeight();
    }
  };
  const walletDiscoverySupported = useMemo(() => {
    const supported = walletRegistry && Object.keys(walletRegistry.default || {}).length > 0 && Object.keys(walletRegistry.others || {}).length > 0;
    return supported;
  }, [walletRegistry]);
  const allUniqueButtons = useMemo(() => {
    const uniqueButtonSet = new Set();
    return customConnectorButtons.concat(allExternalButtons).filter(button => {
      if (uniqueButtonSet.has(button.name)) return false;
      uniqueButtonSet.add(button.name);
      return true;
    });
  }, [allExternalButtons, customConnectorButtons]);
  const defaultButtonKeys = useMemo(() => new Set(Object.keys(walletRegistry.default)), [walletRegistry]);
  const defaultButtons = useMemo(() => {
    // display order: default injected buttons > custom adapter buttons > default non-injected buttons
    const buttons = [...allExternalButtons.filter(button => button.hasInjectedWallet && defaultButtonKeys.has(button.name)), ...customConnectorButtons, ...allExternalButtons.filter(button => !button.hasInjectedWallet && defaultButtonKeys.has(button.name))].sort((a, b) => {
      // favor MetaMask over other wallets
      if (a.name === WALLET_CONNECTORS.METAMASK && b.name === WALLET_CONNECTORS.METAMASK) {
        // favor installed MetaMask over non-installed MetaMask
        if (a.isInstalled) return -1;
        if (b.isInstalled) return 1;
        // favor injected MetaMask over non-injected MetaMask
        if (a.hasInjectedWallet) return -1;
        if (b.hasInjectedWallet) return 1;
        return 0;
      }
      if (a.name === WALLET_CONNECTORS.METAMASK) return -1;
      if (b.name === WALLET_CONNECTORS.METAMASK) return 1;
      return 0;
    });
    const buttonSet = new Set();
    return buttons.filter(button => {
      if (buttonSet.has(button.name)) return false;
      buttonSet.add(button.name);
      return true;
    }).filter(button => {
      var _button$chainNamespac;
      return selectedChain === "all" || ((_button$chainNamespac = button.chainNamespaces) === null || _button$chainNamespac === void 0 ? void 0 : _button$chainNamespac.includes(selectedChain));
    });
  }, [allExternalButtons, customConnectorButtons, defaultButtonKeys, selectedChain]);
  const installedWalletButtons = useMemo(() => {
    const visibilityMap = connectorVisibilityMap;
    return Object.keys(config).reduce((acc, localConnector) => {
      if (localConnector !== WALLET_CONNECTORS.WALLET_CONNECT_V2 && visibilityMap[localConnector]) {
        acc.push({
          name: localConnector,
          displayName: config[localConnector].label || localConnector,
          hasInjectedWallet: config[localConnector].isInjected,
          hasWalletConnect: false,
          hasInstallLinks: false
        });
      }
      return acc;
    }, []);
  }, [connectorVisibilityMap, config]);
  const handleWalletSearch = e => {
    const searchValue = e.target.value;
    setWalletSearch(searchValue);
  };
  const handleChainFilterChange = chain => {
    setSelectedChain(chain);
    setIsShowAllWallets(false);
  };
  const filteredButtons = useMemo(() => {
    if (walletDiscoverySupported) {
      return [...allUniqueButtons.filter(button => button.hasInjectedWallet), ...allUniqueButtons.filter(button => !button.hasInjectedWallet)].sort((a, _) => a.name === WALLET_CONNECTORS.METAMASK ? -1 : 1).filter(button => selectedChain === "all" || button.chainNamespaces.includes(selectedChain)).filter(button => button.name.toLowerCase().includes(walletSearch.toLowerCase()));
    }
    return installedWalletButtons;
  }, [walletDiscoverySupported, installedWalletButtons, walletSearch, allUniqueButtons, selectedChain]);
  const externalButtons = useMemo(() => {
    if (walletDiscoverySupported && !walletSearch && !isShowAllWallets) {
      return defaultButtons;
    }
    return filteredButtons;
  }, [walletDiscoverySupported, walletSearch, filteredButtons, defaultButtons, isShowAllWallets]);
  const totalExternalWalletsCount = useMemo(() => filteredButtons.length, [filteredButtons]);
  const initialWalletCount = useMemo(() => {
    if (isShowAllWallets) return totalExternalWalletsCount;
    return walletDiscoverySupported ? defaultButtons.length : installedWalletButtons.length;
  }, [walletDiscoverySupported, defaultButtons, installedWalletButtons, isShowAllWallets, totalExternalWalletsCount]);

  /**
   * Wallet click logic
   * - For installed wallets
   *  - For MetaMask non-injected on desktop, show QR code for connection
   *  - Ask user to select a chain namespace if it has multiple namespaces
   *  - Otherwise, use their connectors to connect
   * - For wallet-discovery wallets (not installed)
   *  - On desktop, show QR code for connection if wallet connect v2 is supported, otherwise show install links
   *  - On mobile, open deeplink with wallet connect uri (won't go into this function as it'll open the deeplink)
   */
  const handleWalletClick = button => {
    analytics === null || analytics === void 0 || analytics.track(ANALYTICS_EVENTS.EXTERNAL_WALLET_SELECTED, {
      connector: button.isInstalled ? button.name : button.hasWalletConnect ? WALLET_CONNECTORS.WALLET_CONNECT_V2 : "",
      wallet_name: button.displayName,
      is_installed: button.isInstalled,
      is_injected: button.hasInjectedWallet,
      chain_namespaces: button.chainNamespaces,
      has_wallet_connect: button.hasWalletConnect,
      has_install_links: button.hasInstallLinks,
      has_wallet_registry_item: !!button.walletRegistryItem,
      total_external_wallets: allUniqueButtons.length
    });
    log.info("handleWalletClick", button);

    // for installed wallets
    if (button.isInstalled) {
      var _button$chainNamespac2;
      // for MetaMask non-injected on desktop, show QR code for connection
      if (button.name === WALLET_CONNECTORS.METAMASK && !button.hasInjectedWallet && deviceDetails.platform === "desktop") {
        handleExternalWalletClick({
          connector: button.name
        });
        setSelectedButton(button);
        setSelectedWallet(true);
        setCurrentPage(CONNECT_WALLET_PAGES.SELECTED_WALLET);
        handleWalletDetailsHeight();
        return;
      }

      // show chain namespace selector if the button has multiple chain namespaces
      if (((_button$chainNamespac2 = button.chainNamespaces) === null || _button$chainNamespac2 === void 0 ? void 0 : _button$chainNamespac2.length) > 1) {
        setBodyState(_objectSpread(_objectSpread({}, bodyState), {}, {
          multiChainSelector: {
            show: true,
            wallet: button
          }
        }));
        return;
      }

      // otherwise, use their connectors to connect
      handleExternalWalletClick({
        connector: button.name
      });
      return;
    } else {
      // show QR code if wallet connect v2 is supported
      if (button.hasWalletConnect) {
        setSelectedButton(button);
        setSelectedWallet(true);
        setCurrentPage(CONNECT_WALLET_PAGES.SELECTED_WALLET);
        handleWalletDetailsHeight();
      } else {
        // otherwise, show install links
        setBodyState(_objectSpread(_objectSpread({}, bodyState), {}, {
          installLinks: {
            show: true,
            wallet: button
          }
        }));
      }
    }
  };
  const handleMoreWallets = () => {
    setIsShowAllWallets(true);
  };
  const qrCodeValue = useMemo(() => {
    if (!selectedWallet) return null;
    if (selectedButton.name === WALLET_CONNECTORS.METAMASK && !selectedButton.hasInjectedWallet) {
      return metamaskConnectUri;
    }
    return walletConnectUri;
  }, [metamaskConnectUri, selectedButton, selectedWallet, walletConnectUri]);
  const disableBackButton = useMemo(() => {
    // If wallet is selected, show the back button
    if (selectedWallet) return false;
    // Otherwise, if external wallet mode only, login screen is skipped so back button is not needed
    if (isExternalWalletModeOnly) return true;
    return false;
  }, [selectedWallet, isExternalWalletModeOnly]);
  return /*#__PURE__*/jsxs("div", {
    className: "w3a--relative w3a--flex w3a--flex-1 w3a--flex-col w3a--gap-y-4",
    children: [/*#__PURE__*/jsx(ConnectWalletHeader, {
      disableBackButton: disableBackButton,
      onBackClick: handleBack,
      currentPage: currentPage,
      selectedButton: selectedButton
    }), selectedWallet ? /*#__PURE__*/jsx(ConnectWalletQrCode, {
      qrCodeValue: qrCodeValue,
      isDark: isDark,
      selectedButton: selectedButton,
      primaryColor: (_selectedButton$walle = selectedButton.walletRegistryItem) === null || _selectedButton$walle === void 0 ? void 0 : _selectedButton$walle.primaryColor,
      logoImage: `https://images.web3auth.io/login-${selectedButton.name}.${selectedButton.imgExtension}`
    }) : /*#__PURE__*/jsxs("div", {
      className: "w3a--flex w3a--flex-col w3a--gap-y-2",
      children: [chainNamespace.length > 1 && /*#__PURE__*/jsx(ConnectWalletChainFilter, {
        isDark: isDark,
        isLoading: isLoading,
        selectedChain: selectedChain,
        setSelectedChain: handleChainFilterChange,
        chainNamespace: chainNamespace
      }), /*#__PURE__*/jsx(ConnectWalletSearch, {
        totalExternalWalletCount: totalExternalWalletsCount,
        isLoading: isLoading,
        walletSearch: walletSearch,
        handleWalletSearch: handleWalletSearch,
        buttonRadius: buttonRadius
      }), /*#__PURE__*/jsx(ConnectWalletList, {
        externalButtons: externalButtons,
        isLoading: isLoading,
        totalExternalWalletsCount: totalExternalWalletsCount,
        initialWalletCount: initialWalletCount,
        handleWalletClick: handleWalletClick,
        handleMoreWallets: handleMoreWallets,
        isDark: isDark,
        deviceDetails: deviceDetails,
        walletConnectUri: walletConnectUri,
        buttonRadius: buttonRadius
      })]
    })]
  });
}

export { ConnectWallet as default };
