import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { isApi } from "@equilab/api";
import { transformBalance } from "@equilab/utils";
import BigNumber from "bignumber.js";
import React from "react";
import { t } from "ttag";
import { useAssets } from "../../contexts/polkadot/assets";
import { useApi } from "../../contexts/polkadot/api";
import { useNetwork } from "../../contexts/polkadot/network";
import { useBase } from "../../contexts/substrate/base";
import { useAsyncMemo } from "../../hooks/async";
import { trimNumber } from "../../utils/format";
import Button from "../button";
import { Box } from "../grid";
import Input from "../input";
import Select from "../select";
import Text from "../text";
import BackBtn from "./back";
import Tooltip from "../tooltip-base";
import { ActionWrapper, WithdrawAddressWithTooltip, WithdrawEthBnbWarning, } from "./styled";
import { useTheme } from "styled-components";
const MULTIPLIER = new BigNumber(10).pow(-9);
const Withdraw = ({ account, onClose, onChange, onSuccess, onError, extrinsic, balance, token, setToken, config, }) => {
    const { network } = useNetwork();
    const { currencies, native } = useAssets();
    const [fee, setFee] = React.useState();
    const [amount, setAmount] = React.useState();
    const [address, setAddress] = React.useState("");
    const [addressError, setAddressError] = React.useState();
    const [pending, setPending] = React.useState(false);
    const [crossChainIndex, setCrossChainIndex] = React.useState(0);
    const { api } = useApi();
    const theme = useTheme();
    const defaultChainName = React.useMemo(() => (api?._type === "Gens" ? "Genshiro" : "Equilibrium"), [api]);
    const currentChainConfig = React.useMemo(() => config?.[token], [config[token]]);
    const chainBridgeFee = useAsyncMemo(async () => {
        const cfg = currentChainConfig[crossChainIndex];
        if (isApi(api, "Gens") && cfg) {
            const fee = api?._api.consts.chainBridge?.fee ??
                // @ts-ignore
                (await api?._api.query.chainBridge.fees(cfg.nativeChainId));
            if (fee) {
                // @ts-ignore
                return MULTIPLIER.times(fee?.toString(10));
            }
        }
    }, [api, currentChainConfig, crossChainIndex]);
    const configMut = React.useRef();
    React.useEffect(() => {
        configMut.current = currentChainConfig;
    }, [currentChainConfig]);
    React.useEffect(() => {
        setCrossChainIndex(0);
    }, [token]);
    const placeholder = React.useMemo(() => currentChainConfig?.[crossChainIndex]?.addressPlaceholder ??
        "5".padEnd(48, "X"), [token, crossChainIndex, currentChainConfig]);
    const tokenBalance = React.useMemo(() => balance?.[token], [balance, token]);
    const { validateSubstrateAddress } = useBase();
    React.useEffect(() => {
        const cfg = configMut.current?.[crossChainIndex];
        if (address && cfg) {
            const validate = cfg.addressValidation ?? validateSubstrateAddress;
            if (!validate(address)) {
                setAddressError(_jsx("div", { style: { position: "absolute" }, children: t `Wrong address` }));
                return;
            }
            else {
                setAddressError(undefined);
            }
        }
        if (address && amount && token) {
            onChange?.(amount, token, address, cfg);
        }
    }, [
        amount,
        token,
        address,
        onChange,
        crossChainIndex,
        validateSubstrateAddress,
    ]); // TODO config to mutable
    const withdrawAll = React.useCallback((e) => {
        e.preventDefault();
        if (tokenBalance) {
            setAmount(tokenBalance.toString());
        }
    }, [tokenBalance]);
    const onWithdraw = React.useCallback(async () => {
        if (extrinsic) {
            setPending(true);
            try {
                const unsub = await extrinsic.signAndSend(account.address, {
                    nonce: -1,
                }, (result) => {
                    try {
                        if (result.status.isInBlock || result.status.isFinalized) {
                            setPending(false);
                            unsub();
                            for (const { event: { data, section, method }, } of result.events) {
                                if (section === "system" && method === "ExtrinsicSuccess") {
                                    onSuccess?.();
                                    onClose?.();
                                }
                                if (section === "system" && method === "ExtrinsicFailed") {
                                    const [error] = data;
                                    // @ts-ignore
                                    if (error.isModule) {
                                        onError?.(error.asModule);
                                    }
                                    else {
                                        onError?.(error?.toString());
                                    }
                                }
                            }
                        }
                    }
                    catch (e) {
                        if (e instanceof Error) {
                            onError?.(e.message);
                        }
                        else {
                            console.error("UNKNOWN ERROR");
                        }
                        setPending(false);
                    }
                });
            }
            catch (e) {
                if (e instanceof Error) {
                    onError?.(e.message);
                }
                else {
                    console.error("UNKNOWN ERROR");
                }
                setPending(false);
            }
        }
    }, [account.address, extrinsic, onSuccess, onError]);
    React.useEffect(() => {
        (async () => {
            if (extrinsic) {
                const info = await extrinsic.paymentInfo(account.address, {
                    nonce: -1,
                });
                setFee(transformBalance(info.partialFee));
            }
        })();
    }, [account, extrinsic]);
    const showEthBnbWarning = token === "Eth" || token === "Bnb";
    return (_jsxs(_Fragment, { children: [_jsx(BackBtn, { onClose: onClose }), _jsxs(ActionWrapper, { className: "ui-action-wrapper", children: [_jsxs("div", { className: "input-token-row", children: [_jsx(Input, { title: t `Amount to transfer`, placeholder: "0", value: amount ?? "", onChange: (val) => {
                                    setAmount(trimNumber(val));
                                }, disabled: pending, width: "156px", subscript: tokenBalance?.gt(0) && (_jsxs(Text.F2, { style: { position: "relative", top: 14 }, children: [t `Balance`, ":\u00A0", _jsx("a", { onClick: withdrawAll, href: "#", children: tokenBalance?.toFixed(4, 1) })] })), amount: true, theme: theme?.input }), _jsx(Select, { onSelect: (val) => setToken(val), preselectedKey: token, width: "96px", disabled: pending, theme: theme?.select, children: currencies?.map((token) => (_jsx(Select.Option, { style: { color: "#002445" }, children: token.toUpperCase() }, token))) })] }), currentChainConfig?.length ? (_jsx("div", { className: "row withdraw-destination", style: {
                            position: "relative",
                            zIndex: 2,
                        }, children: _jsxs(Select, { disabled: !currentChainConfig?.length, onSelect: (data) => {
                                // TODO make less hacky maybe refactor select component
                                const index = parseInt(data);
                                setCrossChainIndex(Number.isFinite(index) ? index : -1);
                            }, title: t `Destination chain`, width: "100%", preselectedKey: currentChainConfig?.[crossChainIndex]
                                ? `${crossChainIndex}${currentChainConfig?.[crossChainIndex]?.name}`
                                : "equilibrium", theme: theme?.select, children: [currentChainConfig?.map((chain, index) => (_jsx(Select.Option, { children: chain.name }, index + chain.name))), _jsx(Select.Option, { children: defaultChainName }, "equilibrium")] }) })) : undefined, _jsx("div", { className: "row address-row", children: _jsx(Input, { error: addressError, title: _jsxs(WithdrawAddressWithTooltip, { children: [t `Address`, showEthBnbWarning && (_jsx(Tooltip, { openOn: "hover", content: _jsx(_Fragment, { children: t `Please use valid ETH/BSC address and never withdraw funds directly to an exchange.` }) }))] }), width: "100%", placeholder: placeholder, onChange: setAddress, value: address, theme: theme?.input }) }), _jsxs(WithdrawEthBnbWarning, { children: [_jsx("div", { children: t `Warning!` }), _jsx("div", { children: t `Do NOT transfer funds to exchanges directly. They may get lost.` }), showEthBnbWarning && (_jsx("div", { style: { marginTop: 8 }, children: t `You will receive w${token.toUpperCase()} - wrapped tokens, to receive a native token, please unwrap these tokens in the destination blockchain` }))] }), _jsxs(Box, { className: "withdraw-submit", p: "12px 16px", children: [_jsx(Button, { width: "100%", size: "sm", dark: true, onClick: onWithdraw, disabled: !!addressError ||
                                    !extrinsic ||
                                    !Number(amount) ||
                                    !tokenBalance ||
                                    tokenBalance.lt(amount ?? 0) ||
                                    pending, pending: pending, children: t `Withdraw` }), fee && (_jsxs(Box, { mt: "10px", children: [_jsxs(Text.F2, { className: "title", children: [t `Estimated transaction fee`, ":"] }), _jsxs(Text.F1, { children: [fee.toFixed(3), " ", native.toUpperCase()] }), chainBridgeFee.data && (_jsxs(_Fragment, { children: [_jsxs(Text.F2, { className: "title", children: [t `Chainbridge fee`, ":"] }), _jsxs(Text.F1, { children: [chainBridgeFee.data?.toFixed(2), " ", native.toUpperCase()] })] }))] }))] })] })] }));
};
export default Withdraw;
//# sourceMappingURL=withdraw.js.map