<template>
  <div>
    <div>
      <div class="swap">
        <div class="container">
          <div class="box">
            <van-row type="flex"
                     justify="space-between"
                     class="select_currency">
              <van-col class="currency_right">
                <div class="balance">{{$t('lang.swap20')}}</div>
                <div class="balance be"
                     @click="handleToMax">{{ fromCur.balance ? $t('lang.swap22') : '' }} {{ significantDigits(fromCur.balance) }}</div>

              </van-col>
            </van-row>
            <van-row type="flex"
                     justify="space-between"
                     class="btRow">
              <van-col :span="15"
                       class="title">
                <van-field type="number"
                           v-model="fromInput"
                           @input="hanldeInputFrom"
                           placeholder="0.0"
                           class="van-field"
                           input-align="" />
              </van-col>
              <van-col :span="8">
                <div v-if="fromCur.name"
                     class="selectedCurrency">

                  <div class="tokenDetail"
                       @click="handleGetCurrency('from')">
                    <van-image round
                               class="tokenImg"
                               height="20px"
                               :src="fromCur.logoUrl" />
                    <div>{{ fromCur.symbol }}</div>
                    <img class="arrows"
                         src="@/assets/img/arrows.png" />
                  </div>
                </div>
                <div v-else
                     class="tokenSymbol"
                     @click="handleGetCurrency('from')">{{ $t('lang.swap24') }}</div>
              </van-col>
            </van-row>
            <div class="maxWord">
              <span @click="handleToMax">MAX</span>
            </div>
          </div>
          <img src="@/assets/img/exchanges.png"
               @click="handleTurnAround"
               alt
               class="iconDown_img" />
          <div class="box">
            <van-row type="flex"
                     justify="space-between"
                     class="select_currency">

              <van-col class="currency_right">
                <div class="balance">{{$t('lang.swap25')}}</div>
                <div class="balance be">{{ fromCur.balance ? $t('lang.swap22') : '' }}{{ significantDigits(toCur.balance) }}</div>
              </van-col>
            </van-row>
            <van-row type="flex"
                     justify="space-between"
                     class="btRow">
              <van-col :span="15"
                       class="title">
                <van-field type="number"
                           v-model="toInput"
                           @input="hanldeInputTo"
                           placeholder="0.0"
                           class="van-field"
                           input-align="" />
              </van-col>
              <van-col :span="8"
                       @click="handleGetCurrency('to')">
                <div v-if="toCur.name"
                     class="selectedCurrency">
                  <div class="tokenDetail">
                    <van-image round
                               class="tokenImg"
                               height="20px"
                               :src="toCur.logoUrl" />
                    <div>{{ toCur.symbol }}</div>
                    <img class="arrows"
                         src="@/assets/img/arrows.png" />
                  </div>
                </div>
                <div v-else
                     class="tokenSymbol">{{ $t('lang.swap24') }}</div>
              </van-col>
            </van-row>

          </div>
          <!-- <van-row type="flex"
                   justify="space-between">
            <div class="slipWrap">
              <div class="logo">
                <img src="@/assets/img/bnb.png"
                     class="slipWrap_logo">
                <span>BNBD</span>
              </div>
              <div class="address">
                <span>{{ $t('lang.swap380') }} : {{getAccount}}</span>
              </div>
            </div>
          </van-row> -->
          <div class="button">
            <van-button type="primary"
                        class="swapBtn"
                        v-if="!account"
                        @click="handleLogin">{{ $t('lang.swap26') }}</van-button>
            <van-button type="default"
                        class="swapBtn"
                        v-else-if="insufficientLiquidityShow"
                        disabled>{{ $t('lang.swap27') }}</van-button>
            <van-button type="default"
                        class="swapBtn"
                        v-else-if="getNoInputBtnShow"
                        disabled>{{ $t(lang.swap496) }}</van-button>
            <van-button type="default"
                        class="swapBtn"
                        v-else-if="getNoBalanceBtnShow"
                        disabled>{{ $t('lang.swap29') }}</van-button>
            <van-button type="default"
                        class="swapBtn"
                        v-else-if="getNoSelectBtnShow"
                        disabled>{{ $t('lang.swap30') }}</van-button>
            <van-button type="primary"
                        class="swapBtn"
                        :loading="approveLoading"
                        loading-text="Approving..."
                        v-else-if="allowanceToRouter"
                        @click="handleApprove">{{ $t('lang.swap31') }}</van-button>
            <van-button type="primary"
                        class="swapBtn"
                        v-else-if="getWrap"
                        @click="handleDeposit">{{ $t('lang.swap32') }}</van-button>
            <van-button type="primary"
                        class="swapBtn"
                        v-else-if="getWithdraw"
                        @click="handleWithdraw">{{ $t('lang.swap33') }}</van-button>
            <van-button type="default"
                        class="swapBtn"
                        disabled
                        v-else-if="portion >= 20 && !this.expert"
                        @click="handleWithdraw">{{ $t('lang.swap34') }}</van-button>
            <van-button type="primary"
                        class="swapBtn"
                        :loading="swapLoading"
                        loading-text="Waitting"
                        v-else
                        @click="flashRight">{{ $t('lang.swap35') }}</van-button>
          </div>
        </div>
      </div>
    </div>

    <van-popup v-if="tokenListShow"
               v-model="tokenListShow"
               round>
      <currency-list @listenClose="handleTokenListClose"
                     @listenSelecteCurrency="handlerSelecteCurrency" />
    </van-popup>
    <van-popup v-model="settingShow"
               round>
      <SettingsModal @listenClose="handleSettingClose" />
    </van-popup>
    <van-popup v-model="swapDetailShow"
               :round="true"
               @closed="handleSwapDetailClosed">
      <swap-detail @listenClose="handleSwapDetailClose"
                   @listenConfirm="handleConfirm"
                   :fromCur="fromCur"
                   :toCur="toCur"
                   :swapDetail="swapDetail"
                   :portion="portion" />
    </van-popup>
    <van-popup v-model="pendingDetailShow"
               round
               @closed="handlePendingSwapClosed">
      <pending-swap @listenClose="handlePendingSwapClose"
                    :pendingDetail="pendingDetail"
                    :fromCur="fromCur"
                    :toCur="toCur" />
    </van-popup>
    <van-popup v-model="transactionRecordShow"
               round>
      <transaction-record @listenClose="handleTransactionRecordClose" />
    </van-popup>
    <van-popup v-model="VisualChartShow"
               round
               position="bottom">
      <visual-chart @VisualChartClose="visualChartClose"></visual-chart>
    </van-popup>
    <van-popup v-model="swapPopupShow"
               round>
      <SwapPopup @cancelButton="popupSwitch"
                 @switch="swapSwitch"
                 :swapPopupData="swapPopupData"
                 :toCur="toCur"
                 :fromCur="fromCur"
                 :portion="portion"></SwapPopup>
    </van-popup>
  </div>
</template>

<script>
import CurrencyList from '@/components/CurrencyList.vue';
import SwapDetail from '@/views/swap/SwapDetail.vue';
import PendingSwap from '@/views/swap/PendingSwap.vue';
import TransactionRecord from '@/views/swap/TransactionRecord.vue';
import VisualChart from '@/views/swap/VisualChart.vue';
import SwapPopup from '@/views/swap/SwapPopup.vue';

import { mapState } from 'vuex';
import { formatAmount, parseAmount, accMul, accDiv, toFixed, accAdd, accSub, accGt, significantDigits, gasProcessing } from '@/utils/format.js';
import { isBnb } from '@/utils/verify.js';
import { getJackRouterAddress } from '@/utils/addressHelp';
import { MaxUint256 } from '@ethersproject/constants';
import { getErc20Contract, getJackRouterContract, getJackPairContract, getJackFactoryContract } from '@/utils/contractHelp';
import SettingsModal from '@/components/SettingsModal.vue';
import { simpleRpcProvider } from '@/utils/provider';
import { useJackRouterContract, useErc20Contract, useWethContract } from '@/utils/useContract';
import { getAllPair } from '@/utils/pairHelp';
import web3 from 'web3';
export default {
  name: 'Home',
  data () {
    return {
      fromBalance: '',
      tokenListShow: false, //选择代币列表
      settingShow: false, //设置滑点
      isShow: true, //是否展示余额
      approveLoading: false, //授权loading
      swapLoading: false,
      pendingDetailShow: false, //等待交换弹窗
      transactionRecordShow: false, //交易记录
      pendingDetail: { status: 0, hash: '', fromInput: '', toInput: '' },
      allPaths: [], //所有的多路径
      currentPaths: [], //当前所有多路径
      pathIndex: -1, //当前选择的多路径
      pathRouter: '',
      insufficientLiquidityShow: false, //当固定输出时，大于池子深度
      fromInput: '', //from输入框
      fromCur: {
        name: 'BNB',
        symbol: 'BNB',
        address: '0xc945fD8fe31A454ce821CB4514c7761aaB7b7BE0',
        chainId: 97,
        decimals: 18,
        balance: '',
        logoUrl: require('@/assets/img/bnb.png'),
      },
      toInput: '',
      toCur: {
        balance: '',
        name: '',
        symbol: '',
        address: '',
        chainId: '',
        decimals: '',
        logoUrl: '',
      },
      tokenSource: 'from',
      priceDirection: false,
      price: '',
      priceShow: false,
      inputSource: '',
      allowanceToRouter: false, //显示是否需要授权
      swapDetailShow: false, //确认交换弹窗
      swapDetail: { fromInput: '', toInput: '', amountIn: 0, amountInMax: 0, amountOut: 0, amountOutMin: 0, path: [], to: '', deadline: 0, inputSource: 'from', fee: 0 },
      chartShow: true,
      VisualChartShow: false, //数据图弹窗状态
      portion: undefined,
      switchVersionShow: '0',
      less: '<',
      swapPopupShow: false, //确认交换弹窗
      swapPopupData: {
        swapQuantity: '0',
        swapTitle: '警告',
        swapContent: '内容',
      },
      site: '',
    };
  },
  mounted () { },
  beforeDestroy () {
    //清除定时器
    window.clearInterval(this.timer);
    window.clearInterval(this.timerBalance);
  },
  async created () {
    //获取余额
    this.initialization();
    console.log(this.$route.query, 'aaaaaaaaa');
    this.site = this.$route.query.invite_address ? this.$route.query.invite_address : '';
    // if (this.$route.query.invite_address) {
    //   let data = {
    //     recommendAddress: this.$route.query.invite_address,
    //   };
    //   invite.userBind(data, this.account).then(res => {
    //     if (res.code === 200) {
    //     } else {
    //     }
    //   });
    // }
  },
  watch: {
    account () {
      //获取账号
      this.initialization();
    },
  },
  components: {
    CurrencyList,
    SettingsModal,
    SwapDetail,
    PendingSwap,
    TransactionRecord,
    VisualChart,
    SwapPopup,
  },
  computed: {
    ...mapState(['account', 'provider', 'gasPrice', 'slippage', 'deadline', 'multipath', 'pool', 'expert']),
    getAccount () {
      if (this.account) {
        return '0x...' + this.account.substring(this.account.length - 4, this.account.length);
      } else {
        return '';
      }
    },
    // 是否需要显示余额不足提示
    getNoBalanceBtnShow () {
      if (accGt(this.fromInput, this.fromCur.balance)) {
        return true;
      }
      return false;
    },
    //是否需要显示inputBtn按钮
    getNoInputBtnShow () {
      if ((parseFloat(this.fromInput) === 0 || this.fromInput === '') && this.fromCur.address !== '') {
        return true;
      } else if ((parseFloat(this.toInput) === 0 || this.toInput === '') && this.toCur.address !== '') {
        return true;
      }
      return false;
    },
    // 是否需要显示选择币种
    getNoSelectBtnShow () {
      if (this.fromCur.address == '' || this.toCur.address == '') {
        return true;
      }
      return false;
    },
    // 是否BNB - WBNB
    getWrap () {
      if (isBnb(this.fromCur) && this.toCur.address == this.fromCur.address) {
        return true;
      }
      return false;
    },
    // 是否WBNB - BNB
    getWithdraw () {
      if (isBnb(this.toCur) && this.toCur.address == this.fromCur.address) {
        return true;
      }
      return false;
    },
  },
  methods: {
    bind () {
      let data = {
        recommendAddress: this.$route.query.invite_address,
      };
      invite.userBind(data, this.account).then(res => {
        if (res.code === 200) {
        } else {
        }
      });
    },
    //判断是否登录
    handleLogin() {
      let token = this.$route.query.token;
      if (token) {
        localStorage.setItem('website', "app");
        localStorage.setItem('account', this.$route.query.mobile);
        localStorage.setItem('token__' + this.$route.query.mobile, token);
        this.$store.commit('SETACCOUNTS', this.$route.query.mobile);
      }
      this.$store.dispatch('setWebProvider');
    },
    //是否授权
    async handleDeposit () {
      const wethContract = useWethContract();
      const payableAmount = parseAmount(this.fromInput);
      const gas = await wethContract.methods.deposit().estimateGas({ from: this.account, value: payableAmount });
      wethContract.methods
        .deposit()
        .send({ from: this.account, value: payableAmount, gas: gasProcessing(gas), gasPrice: web3.utils.numberToHex(this.gasPrice) })
        .on('transactionHash', hash => {
          const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap15')} ${this.toInput} ${this.toCur.symbol}`;
          const title = this.$t('lang.swap18');
          const transactionsDetail = {
            hash,
            title,
            message,
            addedTime: new Date().getTime(),
            from: this.account,
          };
          this.$store.commit('SETTRANSACTIONS', transactionsDetail);
        })
        .on('receipt', receipt => { })
        .on('error', function (error, receipt) {
          throw error;
        });
    },
    //取出
    async handleWithdraw () {
      const wethContract = useWethContract();
      const wad = parseAmount(this.fromInput);
      const gas = await wethContract.methods.withdraw(wad).estimateGas({ from: this.account });
      wethContract.methods
        .withdraw(wad)
        .send({ from: this.account, gas: gasProcessing(gas), gasPrice: web3.utils.numberToHex(this.gasPrice) })
        .on('transactionHash', hash => {
          const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap16')} ${this.toInput} ${this.toCur.symbol}`;
          const title = this.$t('lang.swap18');
          const transactionsDetail = {
            hash,
            title,
            message,
            addedTime: new Date().getTime(),
            from: this.account,
          };
          this.$store.commit('SETTRANSACTIONS', transactionsDetail);
        })
        .on('receipt', receipt => { })
        .on('error', function (error, receipt) {
          throw error;
        });
    },
    //关闭详情
    handleSwapDetailClose () {
      this.swapDetailShow = false;
    },
    //关闭详情
    handleSwapDetailClosed () {
      this.swapDetail = { fromInput: '', toInput: '', amountIn: 0, amountInMax: 0, amountOut: 0, amountOutMin: 0, path: [], to: '', deadline: 0, inputSource: 'from', fee: 0 };
    },
    handlePendingSwapClose () {
      this.pendingDetailShow = false;
    },
    handleTransactionRecordClose () {
      this.transactionRecordShow = false;
    },
    handlePendingSwapClosed () {
      this.pendingDetail = { status: 0, hash: '', fromInput: '', toInput: '' };
    },
    handleTokenListClose () {
      this.tokenListShow = false;
    },
    handleSettingClose () {
      this.settingShow = false;
    },

    // 获取两边币种余额
    async handleCurBalance () {
      console.log("获取余额");
      if (this.account) {
        if (isBnb(this.fromCur)) {
          console.log("走了这");
          const balance = await simpleRpcProvider.eth.getBalance(this.account);
          this.fromCur.balance = formatAmount(balance);
        }

        if (!isBnb(this.fromCur) && this.fromCur.address != '') {
          const erc20Contract = getErc20Contract(this.fromCur.address);
          const balance = await erc20Contract.methods.balanceOf(this.account).call();
          this.fromCur.balance = formatAmount(balance, this.fromCur.decimals);
        }

        if (isBnb(this.toCur)) {
          const balance = await simpleRpcProvider.eth.getBalance(this.account);
          this.toCur.balance = formatAmount(balance);
        }

        if (!isBnb(this.toCur) && this.toCur.address != '') {
          console.log("走了这李", this.toCur);
          const erc20Contract = getErc20Contract(this.toCur.address);
          const balance = await erc20Contract.methods.balanceOf(this.account).call();
          this.toCur.balance = formatAmount(balance, this.toCur.decimals);
        }
      }
    },
    flashRight () {
      if (this.portion > 10 && this.expert == false) {
        this.swapPopupShow = true;
      } else {
        this.handleSwap();

      }
    },
    // 闪兑
    handleSwap () {
      if (this.fromCur.address == '0x1676BDdf162A800cCb5f9e81b0F402A33c51e06c' || this.toCur.address == '0x1676BDdf162A800cCb5f9e81b0F402A33c51e06c') {
        // Toast.fail(this.$t('lang.swap65'));
        // this.$toast.fail(this.$t('lang.swap65'))
        return;
      }
      const slippage = accDiv(this.slippage, 100);
      this.swapDetail.inputInMax = significantDigits(accAdd(this.fromInput, accMul(this.fromInput, slippage)));
      this.swapDetail.inputOutMin = significantDigits(accSub(this.toInput, accMul(this.toInput, slippage)));
      this.swapDetail.inputSource = this.inputSource;
      this.swapDetail.price = this.price;
      this.swapDetail.fromInput = this.fromInput;
      this.swapDetail.toInput = this.toInput;
      this.swapDetail.fee = accMul(this.swapDetail.inputInMax, 0.003);
      this.swapDetailShow = true;
    },
    //同意
    handleConfirm () {
      const slippage = accDiv(this.slippage, 100);
      const amountIn = parseAmount(this.fromInput, this.fromCur.decimals);
      const amountInMax = toFixed(accAdd(amountIn, accMul(amountIn, slippage)), 0);
      const amountOut = parseAmount(this.toInput, this.toCur.decimals);
      const amountOutMin = toFixed(accSub(amountOut, accMul(amountOut, slippage)), 0);
      let path = [];

      const currentPath = this.currentPaths[this.pathIndex];
      if (currentPath.length == 1) {
        path = [this.fromCur.address, this.toCur.address];
      }

      if (currentPath.length == 2) {
        path = [this.fromCur.address, currentPath[0].toCur.address, currentPath[1].toCur.address];
      }
      const to = this.account;
      const deadline = accAdd(accDiv(Date.parse(new Date()), 1000), accMul(this.deadline, 60));
      this.pendingDetail.fromInput = this.fromInput;
      this.pendingDetail.toInput = this.toInput;
      if (isBnb(this.fromCur) && this.inputSource == 'from') {
        console.log('111111111');
        this.swapExactETHForTokens(amountIn, amountOutMin, path, to, deadline);
        return;
      }

      if (isBnb(this.fromCur) && this.inputSource == 'to') {
        this.swapETHForExactTokens(amountOut, amountInMax, path, to, deadline);
        return;
      }

      if (isBnb(this.toCur) && this.inputSource == 'from') {
        this.swapExactTokensForETH(amountIn, amountOutMin, path, to, deadline);
        return;
      }

      if (isBnb(this.toCur) && this.inputSource == 'to') {
        this.swapTokensForExactETH(amountOut, amountInMax, path, to, deadline);
        return;
      }
      if (this.inputSource == 'from') {
        this.swapExactTokensForTokens(amountIn, amountOutMin, path, to, deadline);
        return;
      }

      if (this.inputSource == 'to') {
        this.swapTokensForExactTokens(amountOut, amountInMax, path, to, deadline);
        return;
      }
    },

    async swapExactETHForTokens (amountIn, amountOutMin, path, to, deadline) {
      const jackRouterContract = useJackRouterContract();
      const gas = await jackRouterContract.methods.swapExactETHForTokens(amountOutMin, path, to, deadline).estimateGas({ from: this.account, value: amountIn });
      this.swapDetailShow = false;
      this.swapLoading = true;
      this.pendingDetailShow = true;
      jackRouterContract.methods
        .swapExactETHForTokens(amountOutMin, path, to, deadline)
        .send({ from: this.account, value: amountIn })
        .on('transactionHash', hash => {
          const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap1')} ${this.toInput} ${this.toCur.symbol}`;
          const title = this.$t('lang.swap18');
          const transactionsDetail = {
            hash,
            title,
            message,
            addedTime: new Date().getTime(),
            from: this.account,
          };
          this.$store.commit('SETTRANSACTIONS', transactionsDetail);
          this.pendingDetail.status = 1;
          this.pendingDetail.hash = hash;
        })
        .on('receipt', receipt => {
          this.swapLoading = false;
        })
        .on('error', (error, receipt) => {
          this.pendingDetail.status = 2;
          this.swapLoading = false;
          throw error;
        });
    },
    async swapETHForExactTokens (amountOut, amountInMax, path, to, deadline) {
      const jackRouterContract = useJackRouterContract();
      const gas = await jackRouterContract.methods
        .swapETHForExactTokens(amountOut, path, to, deadline)
        .estimateGas({ from: this.account, value: amountInMax })
        .catch(async e => {
          const gas = await jackRouterContract.methods.swapExactETHForTokensSupportingFeeOnTransferTokens(amountOut, path, to, deadline).estimateGas({ from: this.account, value: amountInMax });
          this.swapDetailShow = false;
          this.pendingDetailShow = true;
          jackRouterContract.methods
            .swapExactETHForTokensSupportingFeeOnTransferTokens(amountOut, path, to, deadline)
            .send({ from: this.account, value: amountInMax, })
            .on('transactionHash', hash => {
              const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap1')} ${this.toInput} ${this.toCur.symbol}`;
              const title = this.$t('lang.swap18');
              const transactionsDetail = {
                hash,
                title,
                message,
                addedTime: new Date().getTime(),
                from: this.account,
              };
              this.$store.commit('SETTRANSACTIONS', transactionsDetail);
              this.pendingDetail.status = 1;
              this.pendingDetail.hash = hash;
            })
            .on('error', (error, receipt) => {
              this.pendingDetail.status = 2;
              throw error;
            });
        });
      this.swapDetailShow = false;
      this.swapLoading = true;
      this.pendingDetailShow = true;
      jackRouterContract.methods
        .swapETHForExactTokens(amountOut, path, to, deadline)
        .send({ from: this.account, value: amountInMax, gas: gasProcessing(gas), gasPrice: web3.utils.numberToHex(this.gasPrice) })
        .on('transactionHash', hash => {
          const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap1')} ${this.toInput} ${this.toCur.symbol}`;
          const title = this.$t('lang.swap18');
          const transactionsDetail = {
            hash,
            title,
            message,
            addedTime: new Date().getTime(),
            from: this.account,
          };
          this.$store.commit('SETTRANSACTIONS', transactionsDetail);
          this.pendingDetail.status = 1;
          this.pendingDetail.hash = hash;
        })
        .on('receipt', receipt => {
          this.swapLoading = false;
        })
        .on('error', (error, receipt) => {
          this.pendingDetail.status = 2;
          throw error;
        });
    },
    async swapExactTokensForETH (amountIn, amountOutMin, path, to, deadline) {
      const jackRouterContract = useJackRouterContract();
      jackRouterContract.methods
        .swapExactTokensForETH(amountIn, amountOutMin, path, to, deadline)
        .estimateGas({ from: this.account })
        .then(res => {
          this.swapDetailShow = false;
          this.pendingDetailShow = true;
          this.swapLoading = true;
          jackRouterContract.methods
            .swapExactTokensForETH(amountIn, amountOutMin, path, to, deadline)
            .send({ from: this.account, gas: gasProcessing(res), gasPrice: web3.utils.numberToHex(this.gasPrice) })
            .on('transactionHash', hash => {
              const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap1')} ${this.toInput} ${this.toCur.symbol}`;
              const title = this.$t('lang.swap18');
              const transactionsDetail = {
                hash,
                title,
                message,
                addedTime: new Date().getTime(),
                from: this.account,
              };
              this.$store.commit('SETTRANSACTIONS', transactionsDetail);
              this.pendingDetail.status = 1;
              this.pendingDetail.hash = hash;
            })
            .on('receipt', receipt => {
              this.swapLoading = false;
            })
            .on('error', (error, receipt) => {
              this.pendingDetail.status = 2;
              throw error;
            });
        })
        .catch(e => {
          this.$toast('Try increasing your slippage tolerance.');
          this.swapDetailShow = false;
        });
    },
    async swapTokensForExactETH (amountOut, amountInMax, path, to, deadline) {
      const jackRouterContract = useJackRouterContract();
      const gas = await jackRouterContract.methods.swapTokensForExactETH(amountOut, amountInMax, path, to, deadline).estimateGas({ from: this.account });
      this.swapDetailShow = false;
      this.pendingDetailShow = true;
      jackRouterContract.methods
        .swapTokensForExactETH(amountOut, amountInMax, path, to, deadline)
        .send({ from: this.account, gas: gasProcessing(gas), gasPrice: web3.utils.numberToHex(this.gasPrice) })
        .on('transactionHash', hash => {
          const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap1')} ${this.toInput} ${this.toCur.symbol}`;
          const title = this.$t('lang.swap18');
          const transactionsDetail = {
            hash,
            title,
            message,
            addedTime: new Date().getTime(),
            from: this.account,
          };
          this.$store.commit('SETTRANSACTIONS', transactionsDetail);
          this.pendingDetail.status = 1;
          this.pendingDetail.hash = hash;
        })
        .on('error', (error, receipt) => {
          this.pendingDetail.status = 2;
          throw error;
        });
    },
    async swapExactTokensForTokens (amountIn, amountOutMin, path, to, deadline) {
      const jackRouterContract = useJackRouterContract();
      const gas = await jackRouterContract.methods
        .swapExactTokensForTokens(amountIn, amountOutMin, path, to, deadline)
        .estimateGas({ from: this.account })
        .catch(async e => {
          //获取gas报错走这里
          console.log('走了这里上面');
          const gas = await jackRouterContract.methods
            .swapExactTokensForTokensSupportingFeeOnTransferTokens(amountIn, amountOutMin, path, to, deadline)
            .estimateGas({ from: this.account })
            .catch(res => {
              this.swapPopupData.swapQuantity = '1';
              this.swapPopupData.swapTitle = 'error';
              this.swapPopupData.swapContent = 'The transaction cannot succeed due to error: undefined. This is probably an issue with one of the tokens you are swapping.';
              this.swapDetailShow = false;
              this.pendingDetailShow = false;
              this.swapPopupShow = true;
            });
          if (gas) {
            this.swapDetailShow = false;
            this.pendingDetailShow = true;
            jackRouterContract.methods
              .swapExactTokensForTokensSupportingFeeOnTransferTokens(amountIn, amountOutMin, path, to, deadline)
              .send({ from: this.account })
              .on('transactionHash', hash => {
                const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap1')} ${this.toInput} ${this.toCur.symbol}`;
                const title = this.$t('lang.swap18');
                const transactionsDetail = {
                  hash,
                  title,
                  message,
                  addedTime: new Date().getTime(),
                  from: this.account,
                };
                this.$store.commit('SETTRANSACTIONS', transactionsDetail);
                this.pendingDetail.status = 1;
                this.pendingDetail.hash = hash;
              })

              .on('error', (error, receipt) => {
                this.pendingDetail.status = 2;
                this.swapLoading = false;
                throw error;
              });
          }
        });
      if (gas) {
        this.swapDetailShow = false;
        this.pendingDetailShow = true;
        this.swapLoading = true;
        jackRouterContract.methods
          .swapExactTokensForTokens(amountIn, amountOutMin, path, to, deadline)
          .send({ from: this.account })
          .on('transactionHash', hash => {
            const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap1')} ${this.toInput} ${this.toCur.symbol}`;
            const title = this.$t('lang.swap18');
            const transactionsDetail = {
              hash,
              title,
              message,
              addedTime: new Date().getTime(),
              from: this.account,
            };
            this.$store.commit('SETTRANSACTIONS', transactionsDetail);
            this.pendingDetail.status = 1;
            this.pendingDetail.hash = hash;
          })
          .on('receipt', receipt => {
            this.swapLoading = false;
          })
          .on('error', (error, receipt) => {
            this.pendingDetail.status = 2;
            this.swapLoading = false;
            throw error;
          });
      }
    },
    async swapTokensForExactTokens (amountOut, amountInMax, path, to, deadline) {
      const jackRouterContract = useJackRouterContract();
      const gas = await jackRouterContract.methods.swapTokensForExactTokens(amountOut, amountInMax, path, to, deadline).estimateGas({ from: this.account });
      this.swapDetailShow = false;
      this.pendingDetailShow = true;
      this.swapLoading = true;
      jackRouterContract.methods
        .swapTokensForExactTokens(amountOut, amountInMax, path, to, deadline)
        .send({ from: this.account, gas: gasProcessing(gas), gasPrice: web3.utils.numberToHex(this.gasPrice) })
        .on('transactionHash', hash => {
          const message = `${this.fromInput} ${this.fromCur.symbol} ${this.$t('lang.swap1')} ${this.toInput} ${this.toCur.symbol}`;
          const title = this.$t('lang.swap18');
          const transactionsDetail = {
            hash,
            title,
            message,
            addedTime: new Date().getTime(),
            from: this.account,
          };
          this.$store.commit('SETTRANSACTIONS', transactionsDetail);
          this.pendingDetail.status = 1;
          this.pendingDetail.hash = hash;
        })
        .on('receipt', receipt => {
          this.swapLoading = false;
        })
        .on('error', error => {
          this.pendingDetail.status = 2;
          this.swapLoading = false;
          throw error;
        });
    },
    //获取所有的交易对
    async handleGetAllPair () {
      if (this.getWrap || this.getWithdraw) {
        this.allpaths = [];
        return;
      }
      if (this.fromCur.address == '' || this.toCur.address == '') {
        return;
      }
      const allPair = getAllPair(this.fromCur, this.toCur);
      console.log(allPair, 'allPairrrrrrrrrrr');
      const promisePairAddress = allPair.map(item => {
        const jackFactoryContract = getJackFactoryContract();
        const pairAddress = jackFactoryContract.methods.getPair(item.fromCur.address, item.toCur.address).call();
        return pairAddress;
      });
      let allPairAddress = await Promise.all(promisePairAddress);
      let lpPair = [];
      for (let i = 0; i < allPair.length; i++) {
        const lpAddress = allPairAddress[i];
        if (lpAddress == '0x0000000000000000000000000000000000000000') {
          continue;
        }
        lpPair.push({ lpAddress, ...allPair[i] });
      }
      let promiseReserve = lpPair.map(item => {
        const jackPairContract = getJackPairContract(item.lpAddress);
        const reserves = jackPairContract.methods.getReserves().call();
        return reserves;
      });

      const allReserves = await Promise.all(promiseReserve);
      let newlpPair = lpPair.map((item, index) => {
        let newItem = JSON.parse(JSON.stringify(item));
        if (newItem.fromCur.address.toLowerCase() < newItem.toCur.address.toLowerCase()) {
          newItem.fromCur.reserves = allReserves[index]._reserve0;
          newItem.toCur.reserves = allReserves[index]._reserve1;
        } else {
          newItem.fromCur.reserves = allReserves[index]._reserve1;
          newItem.toCur.reserves = allReserves[index]._reserve0;
        }
        return newItem;
      });

      let pathFrom = [];
      for (let i of newlpPair) {
        if (i.fromCur.address == this.fromCur.address) {
          pathFrom.push(i);
        }
      }
      let pathTo = [];

      for (let i of newlpPair) {
        if (i.toCur.address == this.toCur.address) {
          pathTo.push(i);
        }
      }

      let allpaths = [];
      // 算出到底有多少条路径
      for (let i = 0; i < pathFrom.length; i++) {
        const item = pathFrom[i];
        const findItem = pathTo.find(toItem => {
          return item.toCur.address == toItem.fromCur.address;
        });
        if (findItem && findItem.toCur.address == this.toCur.address) {
          allpaths.push([item, findItem]);
          continue;
        }
        if (item.toCur.address == this.toCur.address) {
          allpaths.push([item]);
        }
      }
      this.allpaths = allpaths;
      console.log(this.allpaths, 'this.allpaths');
      if (this.inputSource === 'from') {
        this.getAmountsOut();
      }

      if (this.inputSource === 'to') {
        this.getAmountsIn();
      }
    },

    // from的输入框
    async hanldeInputFrom () {
      this.inputSource = 'from';
      this.getAmountsOut();
    },

    //to的输入框
    hanldeInputTo () {
      this.inputSource = 'to';
      this.getAmountsIn();
    },

    // 是否需要显示授权按钮
    async handleApproveBtnShow () {
      if (isBnb(this.fromCur) || this.fromCur.address == '') {
        this.allowanceToRouter = false;
        return;
      }
      if (this.account) {
        const erc20Contract = getErc20Contract(this.fromCur.address);
        const to = getJackRouterAddress();
        const allowance = await erc20Contract.methods.allowance(this.account, to).call();
        if (allowance == 0) {
          this.allowanceToRouter = true;
        } else {
          this.allowanceToRouter = false;
        }
      }
    },
    // 设置输入框最大值
    async handleToMax () {
      if (isBnb(this.fromCur)) {
        if (this.fromCur.balance > 0.01) {
          this.fromInput = significantDigits(this.fromCur.balance * 1 - 0.01 + '');
        } else {
          this.fromInput = 0;
          console.log('8888888888888888');
        }
      } else {
        this.fromInput = significantDigits(this.fromCur.balance);
      }

      this.inputSource = 'from';
      this.getAmountsOut();
    },
    async initialization () {
      console.log("走了这....");
      this.handleCurBalance();
      // 余额定时器请求
      this.handleTimerBalance();
      if (this.site) {
        this.bind();
      }
    },
    async handleTimerBalance () {
      window.clearTimeout(this.timerBalance);
      this.timerBalance = setInterval(async () => {
        this.handleCurBalance();
      }, 3000);
    },
    // 修改价格方向
    changePriceDirection () {
      this.priceDirection = !this.priceDirection;
      this.getPairPrice();
    },

    //是否显示设置得余额
    handleSettingShow () {
      this.settingShow = true;
    },
    handleRecordShow () {
      this.transactionRecordShow = true;
    },
    async handlerSelecteCurrency (currency) {
      this.tokenListShow = false;
      if (this.tokenSource == 'from') {
        if (currency.address == this.toCur.address && currency.name == this.toCur.name) {
          this.turnAround();
        } else {
          this.fromCur = currency;
        }
      } else {
        if (currency.address == this.fromCur.address && currency.name == this.fromCur.name) {
          this.turnAround();
        } else {
          this.toCur = currency;
        }
      }
      this.handleGetAllPair();
      this.handleApproveBtnShow();
      this.handleCurBalance();
    },

    // 流动池价格更换
    async getPairPrice () {
      if (parseFloat(this.fromInput) === 0 || parseFloat(this.toInput) === 0) {
        this.fromInput = '';
        return;
      }

      if (this.fromCur.address === '' || this.toCur.address === '') {
        this.fromInput = '';
        return;
      }
      const fromInput = parseFloat(this.fromInput);
      const toInput = parseFloat(this.toInput);
      if (this.priceDirection) {
        const price = accDiv(fromInput, toInput);
        this.price = significantDigits(price);
      } else {
        const price = accDiv(toInput, fromInput);
        this.price = significantDigits(price);
      }
      this.priceShow = true;
    },

    //获取实时交易显示
    async getAmountsOut () {
      console.log('输出价格');
      this.insufficientLiquidityShow = false;
      if (parseFloat(this.fromInput) === 0 || this.fromInput == '') {
        this.toInput = '';
        this.priceShow = false;
        return;
      }

      if (this.fromCur.address === '' || this.toCur.address === '') {
        this.toInput = '';
        this.priceShow = false;
        return;
      }

      if (this.getWrap || this.getWithdraw) {
        this.toInput = this.fromInput;
        return;
      }

      if (this.multipath) {
        this.currentPaths = this.allpaths.filter(item => {
          return item.length == 1;
        });
      } else {
        this.currentPaths = this.allpaths;
      }
      let pathIndex = -1;
      let max = 0;
      console.log(this.currentPaths, '当前的多路径');
      for (let i = 0; i < this.currentPaths.length; i++) {
        const pathItem = this.currentPaths[i];
        let amounts = [];
        amounts[0] = parseAmount(this.fromInput, this.fromCur.decimals);
        for (let j = 0; j < pathItem.length; j++) {
          let reserveIn = pathItem[j].fromCur.reserves;
          let reserveOut = pathItem[j].toCur.reserves;
          if (reserveIn == 0 || reserveOut == 0) {
            amounts[j + 1] = 0;
            break;
          }
          let amountInWithFee = accMul(amounts[j], 997);
          console.log('amountInWithFee', amountInWithFee);
          let numerator = accMul(amountInWithFee, reserveOut);
          console.log('numerator', numerator);
          let denominator = accAdd(accMul(reserveIn, 1000), amountInWithFee);
          console.log('denominator', denominator);
          let amountOut = toFixed(accDiv(numerator, denominator), 0);
          console.log('当前输出', amountOut);
          amounts[j + 1] = amountOut;
        }
        if (accGt(amounts[amounts.length - 1], max)) {
          max = amounts[amounts.length - 1];
          console.log('最大值', max);
          pathIndex = i;
        }
      }
      if (pathIndex == -1 || this.currentPaths.length == 0) {
        this.insufficientLiquidityShow = true;
        this.toInput = '';
        return;
      }
      this.pathIndex = pathIndex;
      let list = this.currentPaths[this.pathIndex];
      this.pathRouter = '';
      console.log(list, 'list');
      this.proportion(list);
      for (let k = 0; k < list.length; k++) {
        if (k == 0) {
          console.log('1');
          this.pathRouter = this.pathRouter + list[k].fromCur.symbol + '>' + list[k].toCur.symbol;
        } else {
          console.log('2');
          this.pathRouter = this.pathRouter + '>' + list[k].toCur.symbol;
        }
      }
      this.toInput = formatAmount(max, this.toCur.decimals);
      this.getPairPrice();
    },

    proportion (list) {
      let shuru = this.fromInput * 1 * Math.pow(10, this.fromCur.decimals);
      let one = accDiv(shuru, accAdd(shuru, list[0].fromCur.reserves)) * 100; // 第一个的影响
      this.portion = one;
      if (list.length > 1) {
        let two =
          accDiv(
            accMul(shuru, list[0].toCur.reserves),
            accAdd(accAdd(accMul(shuru, list[0].toCur.reserves), accMul(shuru, list[1].fromCur.reserves)), accMul(list[0].fromCur.reserves, list[1].fromCur.reserves))
          ) * 100;
        this.portion = this.portion + two;
      }
      if (this.portion >= 99.75) {
        this.portion = 99.75;
      }
    },

    async getAmountsIn () {
      this.insufficientLiquidityShow = false;
      if (parseFloat(this.toInput) === 0 || this.toInput == '') {
        this.fromInput = '';
        this.priceShow = false;
        return;
      }

      if (this.fromCur.address === '' || this.toCur.address === '') {
        this.fromInput = '';
        this.priceShow = false;
        return;
      }

      if (this.getWrap || this.getWithdraw) {
        this.fromInput = this.toInput;
        return;
      }

      if (this.multipath) {
        this.currentPaths = this.allpaths.filter(item => {
          return item.length == 1;
        });
      } else {
        this.currentPaths = this.allpaths;
      }
      let pathIndex = -1;
      let min = 0;

      for (let i = 0; i < 1; i++) {
        const pathItem = this.currentPaths[i];
        let amounts = [];

        amounts[pathItem.length] = parseAmount(this.toInput, this.toCur.decimals);
        for (let j = pathItem.length; j > 0; j--) {
          let reserveIn = pathItem[j - 1].fromCur.reserves;
          let reserveOut = pathItem[j - 1].toCur.reserves;
          if (reserveIn == 0 || reserveOut == 0) {
            amounts[j - 1] = 0;
            break;
          }
          let numerator = accMul(accMul(reserveIn, amounts[j]), 1000);
          let denominator = accMul(accSub(reserveOut, amounts[j]), 997);
          let amountIn = toFixed(accAdd(accDiv(numerator, denominator), 1), 0);
          amounts[j - 1] = amountIn;
        }

        if (accGt(amounts[0], 0)) {
          if (i == 0) {
            min = amounts[0];
            pathIndex = i;
          } else if (accGt(min, amounts[0])) {
            min = amounts[0];
            pathIndex = i;
          }
        }
      }

      this.pathIndex = pathIndex;
      // 流动性不足
      if (pathIndex == -1 || this.currentPaths.length == 0) {
        this.insufficientLiquidityShow = true;
        this.fromInput = '';
        return;
      }
      this.fromInput = formatAmount(min, this.fromCur.decimals);
      this.getPairPrice();
    },
    handleGetCurrency (tokenSource) {
      // this.tokenSource = tokenSource;
      // this.tokenListShow = true;
    },

    // 点击反转按钮
    handleTurnAround () {
      // this.turnAround();
      // this.handleGetAllPair();
      // this.handleApproveBtnShow();
      // this.handleCurBalance();
    },

    // 交换from to数据
    turnAround () {
      const tempCurrency = { ...this.toCur };
      this.toCur = { ...this.fromCur };
      this.fromCur = { ...tempCurrency };

      const tempInput = this.toInput;
      this.toInput = this.fromInput;
      this.fromInput = tempInput;

      this.inputSource = this.inputSource === 'from' ? 'to' : 'from';
    },

    async handleApprove () {
      const erc20Contract = useErc20Contract(this.fromCur.address);
      const amount = MaxUint256.toString();
      const to = getJackRouterAddress();
      const gas = await erc20Contract.methods.approve(to, amount).estimateGas({ from: this.account });
      this.approveLoading = true;
      erc20Contract.methods
        .approve(to, amount)
        .send({ from: this.account, gas: gasProcessing(gas), gasPrice: web3.utils.numberToHex(this.gasPrice) })
        .on('transactionHash', hash => {
          const transactionsDetail = {
            title: '',
            hash,
            message: `${this.$t('lang.swap14')} ${this.fromCur.symbol}`,
            addedTime: new Date().getTime(),
            from: this.account,
          };
          this.$store.commit('SETTRANSACTIONS', transactionsDetail);
        })
        .on('receipt', receipt => {
          this.handleApproveBtnShow();
          this.approveLoading = false;
        })
        .on('error', (error, receipt) => {
          this.approveLoading = false;
          this.handleApproveBtnShow();
          throw error;
        });
    },
    visualChartClose () {
      this.VisualChartShow = !this.VisualChartShow;
    },
    // 弹窗开关
    swapSwitch () {
      this.swapPopupShow = !this.swapPopupShow;
    },
    // 弹窗确认按钮
    popupSwitch () {
      this.swapPopupShow = false;
      this.handleSwap();
    },
    significantDigits,
    accSub,
    accMul,
  },
};
</script>

<style lang="less" scoped>
.swap {
  position: relative;

  width: 100%;
  border-radius: 20px;
  .headWrap {
    position: absolute;
    right: 0;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding: 8px 16px;

    .iconSet {
      width: 20px;
      height: 20px;
      // margin-right: 23px;
      cursor: pointer;
    }
    .iconRecord {
      width: 20px;
      height: 20px;
      margin-left: 15px;
      cursor: pointer;
    }
    .iconHash {
      width: 20px;
      height: 20px;
    }
    .headWrap_img {
      display: flex;
      align-items: center;
      justify-content: flex-end;
      background: rgba(199, 199, 199, 0.2);
      border-radius: 14px;
      padding: 4px 14px;
    }
  }
  .container {
    border-radius: 0 0 16px 16px;
    padding: 20px;

    background: #171717;
    .box {
      // padding: 20px 15px;
      // background: @background-gray;
      border-radius: 10px;

      // background: #f8f7f7;
      // border: 1px solid #ffd245;
      // box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.3);
      font-weight: bold;
      .balance {
        font-size: 14px;
        font-weight: normal;

        color: #eceef0;
      }
      .be {
        font-size: 12px;
      }
      .select_currency {
        display: flex;
        align-items: center;

        .currency_right {
          display: flex;
          align-items: center;
          justify-content: space-between;
          width: 100%;
        }
      }
      .btRow {
        display: flex;
        // background: #1e242b;
        align-items: center;
        border-radius: 12px;
        margin-top: 20px;
        // padding: 18px 0 18px;
        // .title {
        //   width: 100%;
        // }
      }
      .van-field {
        border: 1px solid #1e242b !important;
        color: #eceef0;
        background: #333333 !important;
        padding: 0 10px !important;
        /deep/ .van-field__control {
          color: #eceef0 !important;
        }
      }
      .tokenSymbol {
        font-size: 14px;
        border-radius: 8px;
        text-align: right;
        color: #f6bb31;
        // border: 1px solid #f6bb31;

        // background: linear-gradient(228deg, #fdde34 0%, #65fce4 100%);
        padding: 2px 6px;
        cursor: pointer;
      }
      .maxWord {
        // color: #595b5b;
        // background: linear-gradient(228deg, #fdde34 0%, #65fce4 100%);
        // font-size: 10px;
        // font-weight: bold;
        // cursor: pointer;
        // border-radius: 9px;
        // padding: 4px 6px;
        // margin-left: 10px;
        margin-top: 10px;
        display: flex;
        justify-content: flex-end;
        span {
          color: #f6bb31;
          border-radius: 2px 2px 2px 2px;
          border: 1px solid #f6bb31;
          padding: 4px 10px;
        }
      }
      .selectedCurrency {
        display: flex;
        align-items: center;
        justify-content: flex-end;
        .tokenDetail {
          display: flex;
          align-items: center;
          font-size: 14px;
          // border: 1px solid #ffd245;
          border-radius: 4px;

          color: #e8e7f0;
          padding: 2px 6px;
          margin: 0 2px;
          // border: 1px solid #f6bb31;

          cursor: pointer;
          .arrows {
            width: 10px;
            height: 6px;
            margin-left: 6px;
          }
        }
        .tokenImg {
          margin-right: 4px;
          margin-left: 4px;
          width: 16px !important;
          height: 16px !important;
        }
      }
    }

    .iconDown_img {
      width: 30px;
      height: 30px;
      display: block;
      margin: 20px auto;
      cursor: pointer;
      transform: rotate(90deg);
    }
    // .slipWrap {
    //   display: flex;
    //   align-items: center;
    //   font-size: 12px;
    //   font-family: PingFangSC-Medium, PingFang SC;
    //   font-weight: 500;
    //   // color: #65fce4;
    //   margin: 20px 0;
    //   .text {
    //     color: #eceef0;
    //   }
    //   .iconSet {
    //     display: flex;
    //     align-items: center;
    //     color: #fff;
    //     .iconSet_img {
    //       width: 20px;
    //       height: 20px;
    //       margin-left: 6px;
    //     }
    //   }
    // }
  }
}
.button {
  .swapBtn {
    width: 100%;
    height: auto;
    margin-top: 22px;
    font-size: 14px;
    font-weight: bold;
    border-radius: 6px;
    border: 0;
    padding: 8px 0 !important;
  }
  /deep/ .van-button--primary {
    color: #000000;
    background: linear-gradient(321deg, #fdde34 0%, #65fce4 100%);
    border: 0;
  }
  /deep/ .van-button--disabled {
    color: #878995;
    background: #1e242b;
  }
}
.slipWrap {
  color: #ffffff;
  width: 100%;
  background: #333333;
  border-radius: 2px;
  margin: 20px 0 10px;
  padding: 20px;
  .logo {
    display: flex;
    align-items: center;
    color: #fff;
    .slipWrap_logo {
      display: block;
      width: 20px;
      height: 20px;
      border-radius: 50%;
      margin-right: 6px;
    }
  }
  .address {
    font-size: 14px;
    color: #999;
    margin-top: 10px;
  }
}
.current_prompt {
  background: #171717;
  border-radius: 8px;
  padding: 20px 22px 10px;
  margin: 30px 0 10px;
  .price {
    margin-bottom: 10px;
    color: #ffffff;
    .text {
      font-size: 12px;
      font-weight: bold;
    }
    .opppsite {
      height: 10px;
      width: 10px;
    }
  }

  .tips {
    display: flex;
    justify-content: space-between;
    font-size: 12px;
    color: #ffffff;
    margin-bottom: 10px;
    .subtitle {
      color: #ffffff;
    }
    .special_color {
      color: #ffd245;
    }
    .special {
      text-align: right;
    }
  }
}
.data_sheet {
}
</style>
