<template>
  <div class="wallet-container">
    <div class="header">
      <div class="label">Wallet</div>
    </div>
    <div class="horizontal-bar"></div>
    <div class="code" v-if="logined">
      <span class="uuid">{{showAccount}}</span>
      <div v-clipboard:copy="account"
           v-clipboard:success="onCopy"
           v-clipboard:error="onCopyError">
        <svg-icon
          name="copy" class="icCopy"></svg-icon>
      </div>
    </div>
    <div class="tab-bar-net">
      <div class="tab-item"
          v-for="n in nets"
          @click='changeNet(n.id)'
          :key="n.id"
          :class="{'active': currentNet===n.id}"
      >
        <span>{{n.name}}</span>
      </div>
    </div>
    <div class="wallet">
      <total-balance :currencies="currencies"></total-balance>
      <coin-card
        v-for="d in coinList"
        :coin-data="d"
        :process = "showOrderStatus"
        @coin-card-clicked = "onCardClicked"
        :key="d.symbol"></coin-card>
    </div>
    <div class="header ingame"><span class="label">Ingame Currency</span>
    </div>
    <div class="horizontal-bar"></div>
    <div class="wallet">
      <placeholder-panel></placeholder-panel>
      <coin-card
        v-for="d in gameCoinList"
        :coin-data="d"
        :process = "showOrderStatus"
        @coin-card-clicked = "onGameCardClicked"
        :key="d.symbol"></coin-card>
    </div>
    <price-picker-modal></price-picker-modal>
    <div class="order-status" v-show="showOrderStatus">
      <el-tooltip class="item" effect="light" content="Transaction in progress" placement="right">
        <time-loader></time-loader>
      </el-tooltip>
    </div>
  </div>
</template>
<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator'
import TotalBalance, { ICurrentData } from '@/components/market/wallet/TotalBalance.vue'
import CoinCard, { ICoinData } from '@/components/market/wallet/CoinCard.vue'
import GameCoinCard from '@/components/market/wallet/GameCoinCard.vue'
import { AppModule } from '@/store/modules/app'
import PlaceholderPanel from '@/components/market/wallet/PlaceholderPanel.vue'
import ChainManager from '@/chain/ChainManager'
import { CONTRACT_ADDRESS, OFFICE_ACCOUNT } from '@/configs/config_chain'
import { formatPrice } from '@/utils/chain.util'
import { getUserInfo } from '@/api/User'
import PricePickerModal, { SHOW_AMOUNT_MODAL } from '@/components/market/PricePickerModal.vue'
import { EventBus } from '@/utils/event-bus'
import { queryRechargeResult, queryWithdrawalResult, withdrawal } from '@/api/Market'
import { ElLoadingComponent } from 'element-ui/types/loading'
import TimeLoader from '@/components/main/TimeLoader.vue'

const TMP_ORDER_ID = 'tmp_coin_order_id'
@Component({
  name: 'WalletPanel',
  components: {
    TimeLoader,
    PricePickerModal,
    PlaceholderPanel,
    GameCoinCard,
    CoinCard,
    TotalBalance
  }
})
export default class WalletPanel extends Vue {
  private currentNet: number = this.nets[0].id
  chainManager = new ChainManager()
  orderTimer: any = null
  showOrderStatus = false
  historyOrderId: string | null = ''
  loadingInstance: ElLoadingComponent

  get nets() {
    return [...new ChainManager().availableChains.values()]
  }

  get logined() {
    return this.chainManager.isLogined
  }

  @Watch('logined')
  private accountChange() {
    this.changeNet(this.nets[0].id)
    if (this.account) {
      this.updateCurrencies()
      this.updateGameCoins()
      this.checkOrderHistory()
    }
  }

  private currencies: ICurrentData[] = []

  private coinList: ICoinData[] = [
    {
      name: 'CEBG Coin',
      type: 0,
      id: 'cec',
      symbol: 'cec',
      amount: '-',
      icon: require('@/assets/market/cec.png'),
      price: '-',
      btnName: 'Deposit',
      btnDisable: true
    },
    {
      name: 'CEBG Gem',
      type: 0,
      id: 'ceg',
      symbol: 'ceg',
      amount: '-',
      icon: require('@/assets/market/ceg.png'),
      price: '-',
      btnName: 'Deposit',
      btnDisable: true
    }
  ]

  private gameCoinList: ICoinData[] = [
    {
      name: 'CEBG Coin',
      type: 1,
      id: 'diamond',
      symbol: 'gCEC',
      amount: '-',
      icon: require('@/assets/market/cec.png'),
      price: '-',
      btnName: 'Claim',
      btnDisable: true
    },
    {
      name: 'CEBG Gem',
      type: 1,
      id: 'gold',
      symbol: 'gCEG',
      amount: '-',
      icon: require('@/assets/market/ceg.png'),
      price: '-',
      btnName: 'Claim',
      btnDisable: true
    }
  ]

  created() {
    for (const net of this.nets) {
      this.currencies.push({
        name: `W${net.symbol.toUpperCase()}`,
        amount: '-',
        price: '-',
        chain: net.id
      })
    }
  }

  mounted() {
    this.checkOrderHistory()
  }

  updateDefaultData(data: ICoinData) {
    data.amount = '-'
    data.price = '-'
    data.btnDisable = true
    return data
  }

  get showAccount() {
    return AppModule.accountShow
  }

  get account() {
    return AppModule.accountId
  }

  onCopy(e: any) {
    this.$message({
      message: 'You just copied accountId',
      type: 'success',
      duration: 5 * 1000
    })
  }

  onCopyError(e: any) {
    this.$message({
      message: 'Failed to copy texts',
      type: 'error',
      duration: 5 * 1000
    })
  }

  changeNet(net: number) {
    this.currentNet = net
    const chainData = CONTRACT_ADDRESS[net]
    for (let i = 0, l = this.coinList.length; i < l; i++) {
      const data = this.updateDefaultData(this.coinList[i])
      data.chain = net
      data.address = chainData[data.symbol]
      this.$set(this.coinList, i, data)
    }
    this.updateBalanceSet()
  }

  async updateCurrencies() {
    for (let i = 0, l = this.currencies.length; i < l; i++) {
      const data = this.currencies[i]
      const currentData = CONTRACT_ADDRESS[data.chain]
      const eth = await this.chainManager.getBalance(currentData.eth, data.chain)
      data.amount = eth
      this.$set(this.currencies, i, data)
    }
  }

  async updateBalanceSet() {
    const currentData = CONTRACT_ADDRESS[this.currentNet]
    if (currentData) {
      const cec = await this.chainManager.getBalance(currentData.cec, this.currentNet)
      const ceg = await this.chainManager.getBalance(currentData.ceg, this.currentNet)
      console.log(formatPrice(cec, 18), formatPrice(ceg, 18))
      const updateCoinData = (i: number, amount: number) => {
        const cecData = this.coinList[i]
        cecData.amount = formatPrice(amount, 18)
        cecData.btnDisable = amount === 0
        this.$set(this.coinList, i, cecData)
      }
      updateCoinData(0, cec)
      updateCoinData(1, ceg)
    }
  }

  async onCardClicked(data: ICoinData) {
    console.log('on coin card clicked: ', data)
    let value = 0
    try {
      value = await this.pickAmount({
        min: 1,
        max: data.amount,
        title: 'Please input amount to deposit'
      })
    } catch (err) {
      this.$message({
        type: 'info',
        message: 'User cancel'
      })
    }
    if (!value) {
      return
    }
    this.loadingInstance = this.$loading({})
    try {
      const res = await this.beginTransfer(data, value)
      console.log(res)
      const txHash = res.transactionHash
      this.saveTmpOrderInfo(txHash, 0)
      this.beginTraceOrderStatus(txHash, 0)
    } catch (err) {
      console.log(err)
      this.$message({
        type: 'info',
        message: 'error transfer'
      })
    }
    this.loadingInstance?.close()
  }

  async beginTransfer(data: ICoinData, amount: number) {
    return this.chainManager.transferToAccount({
      to: OFFICE_ACCOUNT,
      amount: amount,
      chainId: data.chain!,
      address: data.address!
    })
  }

  async onGameCardClicked(data: ICoinData) {
    console.log('on game card clicked: ', data)
    let value = 0
    try {
      value = await this.pickAmount({
        min: 1,
        max: data.amount,
        title: 'Please input amount to claim'
      })
    } catch (err) {
      this.$message({
        type: 'info',
        message: 'User cancel'
      })
    }
    if (!value) {
      return
    }
    const postData = {
      account: AppModule.accountId,
      type: data.id === 'gold' ? 1 : 2,
      amount: value + '000000000000000000'
    }
    this.loadingInstance = this.$loading({})
    try {
      const res: any = await withdrawal(postData)
      console.log('withdrawal result: ', res)
      const seqId = res.seq_id
      this.saveTmpOrderInfo(seqId, 1)
      this.beginTraceOrderStatus(seqId, 1)
      this.loadingInstance?.close()
    } catch (err) {
      this.loadingInstance?.close()
    }
    console.log('begin claim')
  }

  async updateGameCoins() {
    const data = { account: AppModule.accountId }
    const info: any = await getUserInfo(data)
    for (let i = 0, l = this.gameCoinList.length; i < l; i++) {
      const data = this.gameCoinList[i]
      data.amount = info[data.id] || 0
      data.btnDisable = data.amount === 0
      this.$set(this.gameCoinList, i, data)
    }
  }

  /**
   * 获取用户选择的币的数量
   * @param data
   * @return {Promise<number>}
   */
  pickAmount(data: any) {
    return new Promise<number>((resolve, reject) => {
      data.current = data.current || data.min
      data.confirmFun = (val: number) => {
        resolve && resolve(val)
      }
      data.cancelFun = () => {
        // eslint-disable-next-line prefer-promise-reject-errors
        reject && reject('cancel select')
      }
      EventBus.$emit(SHOW_AMOUNT_MODAL, data)
    })
  }

  /**
   * 查询token->game的订单
   * @param {string} txhash
   * @return {Promise<void>}
   */
  async queryRechargeOrder(txhash: string) {
    const data: any = {
      account: AppModule.accountId,
      txhash
    }
    try {
      const res: any = await queryRechargeResult(data)
      console.log('queryRechargeResult: ', res)
      if (res.state === 1) {
        this.resetTmpOrderId()
        this.showOrderStatus = false
        this.updateGameCoins()
        this.updateBalanceSet()
        this.$alert('Congratulations', 'Deposit Success', { type: 'success', confirmButtonText: 'OK' })
      } else if (res.state === 3) {
        this.resetTmpOrderId()
        this.showOrderStatus = false
        this.updateGameCoins()
        this.updateBalanceSet()
        this.$alert('Sorry', 'Deposit failed', { type: 'error', confirmButtonText: 'OK' })
      }
    } catch (err) {
      console.log(err)
    }
  }

  /**
   * 查询token->game的订单
   * @param {string} seqId
   * @return {Promise<void>}
   */
  async queryWithdrawOrder(seqId: string) {
    const data: any = {
      account: AppModule.accountId,
      seq_id: seqId
    }
    try {
      const res: any = await queryWithdrawalResult(data)
      console.log('queryWithdrawalResult: ', res)
      if (res.state === 1) {
        this.resetTmpOrderId()
        this.showOrderStatus = false
        this.updateGameCoins()
        this.updateBalanceSet()
        this.$alert('Congratulations', 'Claim Success', { type: 'success', confirmButtonText: 'OK' })
      } else if (res.state === 3) {
        this.resetTmpOrderId()
        this.showOrderStatus = false
        this.updateGameCoins()
        this.updateBalanceSet()
        this.$alert('Sorry', 'Claim failed', { type: 'error', confirmButtonText: 'OK' })
      }
    } catch (err) {
      console.log(err)
    }
  }

  checkOrderHistory() {
    const data = this.getTmpOrderInfo()
    if (data && this.account) {
      this.beginTraceOrderStatus(data.orderId, data.type)
    }
  }

  resetTmpOrderId() {
    if (this.orderTimer !== null) {
      clearInterval(this.orderTimer)
      this.orderTimer = null
    }
    this.removeTmpOrderInfo()
    this.loadingInstance?.close()
  }

  saveTmpOrderInfo(orderId: string, type: number) {
    const data = { orderId, type }
    localStorage.setItem(TMP_ORDER_ID, JSON.stringify(data))
  }

  removeTmpOrderInfo() {
    localStorage.removeItem(TMP_ORDER_ID)
  }

  getTmpOrderInfo() {
    const dataStr = localStorage.getItem(TMP_ORDER_ID)
    if (dataStr) {
      try {
        return JSON.parse(dataStr)
      } catch (err) {
        return null
      }
    }
    return null
  }

  beginTraceOrderStatus(orderId: string, type: number) {
    this.showOrderStatus = true
    this.loadingInstance?.close()
    this.orderTimer = setInterval(() => {
      if (type === 0) {
        this.queryRechargeOrder(orderId)
      } else {
        this.queryWithdrawOrder(orderId)
      }
    }, 1000)
  }
}
</script>
<style lang="scss" scoped>
@import '../../../scss/breakpoints.scss';

.wallet-container {
  box-sizing: border-box;
  color: white;
  width: 1440px;
  .tab-bar-net {
    display: flex;
    flex-direction: row;
    margin-bottom: 5px;
    .tab-item{
      display: flex;
      justify-content: center;
      align-items: center;
      flex: none;
      cursor: pointer;
      font-weight: bold;
      font-size: 1em;
      line-height: 1.5em;
      padding: 0.5em 2.125em;
      text-transform: uppercase;
      border: 1px solid #413482;
      height: 2em;
      border-radius: 0.2em;
      color: #bcadf2;
      background: transparent;
      //clip-path: polygon(10% 0, 100% 0, 90% 100%, 0% 100%);
      &:not(:first-child) {
        margin-left: 0.5em;
      }
      &.active {
        color: #ffffff;
        background: #413482;
      }
    }
  }
  .code {
    display: flex;
    align-self: flex-start;
    cursor: pointer;
    margin-bottom: 1.25em;
    .uuid {
      font-size: 1em;
      line-height: 1.5;

      &:active {
        opacity: 0.6;
      }
    }

    .copy {
      margin-left: 0.5em;
    }
  }
  .ingame {
    margin-top: 3.625em;
  }

  .icCopy {
    margin-left: 3.625em;
    align-self: center;
    &:active {
      opacity: 0.6;
    }
  }

  .header {
    display: flex;
    flex-direction: row;
    align-items: center;
    padding-bottom: 0.75em;

    .label {
      font-weight: bolder;
      font-size: 1.375em;
      line-height: 1.27;
      color: #ffffff;
      &.disable {
        @include media('<tablet') {
          color: #3c2885;
        }
      }
      &.ingameCurrency {
        margin-left: 2.1875em;
      }
    }
  }

  .horizontal-bar {
    border: 0;
    height: 1px;
    background: #563cb8;
    margin-bottom: 1.75em;
  }

  .wallet {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
  }
}
.order-status {
  transform: scale(0.3);
  width: 220px;
  height: 220px;
  border-radius: 110px;
  background: white;
  display: flex;
  justify-content: center;
  align-items: center;
  transform-origin: top;
  position: fixed;
  left: 100px;
  top: 100px;
}
@include media('<wide') {
  .wallet-container{
    width: 1024px;
    font-size: 13px;
  }
}
// Mobile
@include media('<tablet') {
  .wallet-container {
    width: 100%;
    .show {
      display: flex !important;
    }
    .hide {
      display: none !important;
    }
    .headerCoin {
      margin-top: 28px;
    }
    .ingame {
      margin-top: 28px;
    }
    .wallet {
      display: flex;
      flex-direction: column;
      align-items: center;
      .coinCard {
        width: 100%;
        margin-bottom: 20px;
      }
    }
    .walletIngame {
      display: none;
    }
  }
}

// Tablet
@include media('>=tablet', '<desktop') {
  .wallet-container {
    width: 100%;
    .ingame {
      margin-top: 38px;
    }
    .headerCoin {
      margin-top: 28px;
    }
    .wallet {
      display: flex;
      flex-direction: row;
      flex-wrap: wrap;
      justify-content: space-between;

      .coinCard {
        width: 293px;
        margin-bottom: 20px;
      }
    }
  }
}

</style>
