<template>
  <div>
    <top-menu class="desk-top" :current-tab="currentTab"></top-menu>
    <section class="mynft">
      <div class="container">
        <div class="wrapper">
          <nft-type-bar :select-idx="nftType" @nft-type-changed="onNftTypeClicked" class="left-bar"></nft-type-bar>
          <sort-select
            :filters="filters"
            :selected-index="nftState"
            @filter-change="filterChange"
          ></sort-select>
        </div>
        <nft-list :nft-datas="nftList" v-if="nftList.length > 0" @activate-clicked="onActivateClick"></nft-list>
        <result-no
          v-if="nftList.length === 0"
          title="No Record."
          desc=""
        ></result-no>
        <pagination
          v-if="totalPage>1"
          :total="totalPage"
          :current="currentPage"
          @to-page="toPage"
          class="page-comp"
        ></pagination>
      </div>
      <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>
    </section>
    <base-footer :auto-size="true">></base-footer>
  </div>
</template>

<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator'
import SearchPanel from '@/components/market/SearchPanel.vue'
import Pagination from '@/components/market/Pagination.vue'
import SearchResult from '@/components/market/SearchResult.vue'
import TopMenu from '@/components/market/TopMenu.vue'
import NftList from '@/components/market/NftList.vue'
import { getNftList } from '@/api/Mall'
import { AppModule } from '@/store/modules/app'
import BaseFooter from '@/components/layout/BaseFooter.vue'
import NftTypeBar from '@/components/market/NftTypeBar.vue'
import SortSelect from '@/components/market/SortSelect.vue'
import ResultNo from '@/components/market/ResultNo.vue'
import { INftData, parseNftData } from '@/types/Nft'
import TimeLoader from '@/components/main/TimeLoader.vue'
import { preActivateNFT, preOpenBox, queryActivateNFTState, queryBoxOpenState } from '@/api/Market'
import { createModal, ZModal } from '@/utils/modal.util'
import RewardModal from '@/components/core/RewardModal.vue'
import { ElLoadingComponent } from 'element-ui/types/loading'
import { UserModule } from '@/store/modules/user'
import ChainManager from '@/chain/ChainManager'
import { CONTRACT_ADDRESS } from '@/configs/config_chain'

const MYSTERY_BOX_CACHE = 'activate_nft_cache'

@Component({
  components: {
    TimeLoader,
    ResultNo,
    SortSelect,
    NftTypeBar,
    BaseFooter,
    NftList,
    SearchResult,
    SearchPanel,
    Pagination,
    TopMenu
  }
})
export default class MyNft extends Vue {
  mobileFilterShow = false
  currentTab = 'mynft'
  nftList: INftData[] = []
  nftType = 1
  nftState = 0
  showOrderStatus = false
  private filters = ['All Items', 'Normal', 'Selling', 'Renting']
  private totalPage = 1
  private currentPage = 1
  private dataCache: Map<any, INftData[]> = new Map()

  private isProcess = false
  private rewardModal: ZModal
  orderTimer: any = null
  loadingInstance: ElLoadingComponent
  chainManager = new ChainManager()

  get accountId() {
    return AppModule.accountId
  }

  get isLogin() {
    return !!UserModule.token && !!AppModule.step
  }

  get boxProxyAddress() {
    return CONTRACT_ADDRESS[AppModule.chainId].nftProxy
  }

  onNftTypeClicked(typeId: number) {
    console.log('nft type clicked: ', typeId)
    if (this.nftType !== typeId) {
      this.nftType = typeId
      this.fetchDatas(1)
    }
  }

  filterChange(id: number) {
    console.log('filter change: ', id)
    if (this.nftState !== id) {
      this.nftState = id
      this.fetchDatas(1)
    }
  }

  @Watch('isLogin')
  private accountChange() {
    console.log('account change: ', AppModule.accountId)
    if (this.accountId) {
      this.fetchDatas(this.currentPage)
      this.checkOrderHistory()
    }
  }

  showFilter(val: boolean) {
    this.mobileFilterShow = val
  }

  async fetchDatas(pageNo: number) {
    if (!AppModule.accountId) {
      return
    }
    const reqData: any = {
      account: AppModule.accountId,
      page: pageNo,
      type: this.nftType
    }
    if (this.nftState > 0) {
      reqData.state = this.nftState - 1
    }
    if (this.dataCache.has(reqData)) {
      this.nftList = this.dataCache.get(reqData)!
    } else {
      this.nftList.length = 0
    }
    const res: any = await getNftList(reqData)
    if (res.nfts) {
      this.nftList.length = 0
      for (const data of res.nfts) {
        const nftData = parseNftData(data)
        this.nftList.push(nftData)
      }
      this.dataCache.set(reqData, this.nftList)
    }
    if (res.page) {
      const page = res.page
      this.totalPage = page.total_pages || 1
      this.currentPage = page.current_page || 1
    }
    console.log(res)
  }

  toPage(pageNo: number) {
    console.log('to page: ', pageNo)
    this.fetchDatas(pageNo)
  }

  showLoading() {
    this.loadingInstance = this.$loading({ background: 'rgba(0, 0, 0, 0.8)' })
  }

  hideLoading() {
    this.loadingInstance?.close()
  }

  async onActivateClick({ tokenId, type }: {tokenId: string, type: number}) {
    console.log('onActivateClick: ', tokenId, type)
    if (!this.isLogin) {
      this.$message({
        message: 'You should login first',
        type: 'warning',
        duration: 5 * 1000
      })
      return
    }
    if (this.isProcess) {
      this.$message({
        message: 'Box open in process',
        type: 'warning',
        duration: 5 * 1000
      })
    }
    this.isProcess = true
    const reqData = {
      token_id: tokenId
    }
    this.showLoading()
    let nonce, signature, nftNew
    try {
      const res: any = await preActivateNFT(reqData)
      nonce = res.nonce
      signature = res.signature
      nftNew = res.new_token_id
    } catch (err) {
      console.log('pre activate err', err)
      this.$message.error('activate nft with pre request error')
      this.hideLoading()
      this.isProcess = false
      return false
    }
    try {
      const result = await this.chainManager.activateOneNft(
        this.boxProxyAddress, tokenId, nftNew, type, nonce, signature)
      console.log('activate nft result: ', result)
      const stateData = { token_id: tokenId, txhash: result.transactionHash }
      localStorage.setItem(MYSTERY_BOX_CACHE, JSON.stringify(stateData))
      this.hideLoading()
      this.beginTraceOrderStatus(stateData)
    } catch (err) {
      console.log(err)
      this.hideLoading()
      this.isProcess = false
      this.$message.error('activate nft with error: ' + err)
    }
  }

  checkOrderHistory() {
    const historyOrderId = localStorage.getItem(MYSTERY_BOX_CACHE)
    if (historyOrderId && this.accountId) {
      try {
        const data = JSON.parse(historyOrderId)
        this.beginTraceOrderStatus(data)
      } catch (err) {
        localStorage.removeItem(MYSTERY_BOX_CACHE)
      }
    }
  }

  beginTraceOrderStatus(cacheData: any) {
    this.showOrderStatus = true
    this.isProcess = true
    this.loadingInstance?.close()
    this.orderTimer = setInterval(() => {
      this.getOrderStatus(cacheData)
    }, 1000)
  }

  async getOrderStatus(data: any) {
    console.log('getOrderStatus: ', data)
    try {
      const res: any = await queryActivateNFTState(data)
      if (res.state === 1) {
        // success
        this.onOpenSuccess(res.nft)
      }
    } catch (err) {
      console.log('query order status error', err)
    }
  }

  resetTmpOrderId() {
    if (this.orderTimer !== null) {
      clearInterval(this.orderTimer)
      this.orderTimer = null
    }
    this.isProcess = false
    localStorage.removeItem(MYSTERY_BOX_CACHE)
    this.loadingInstance?.close()
  }

  async onOpenSuccess(data: any) {
    console.log('open success')
    if (!this.isProcess) {
      return
    }
    this.resetTmpOrderId()
    this.showOrderStatus = false
    const cardList: INftData[] = []
    const nftData = parseNftData(data)
    cardList.push(nftData)
    this.showRewardModal({
      title: 'NFT activate Success',
      cardList
    })
    this.fetchDatas(this.currentPage)
    // this.$alert('Congratulations', 'Open Success', { type: 'success', confirmButtonText: 'OK' })
  }

  showRewardModal(data: any) {
    console.log('show reward modal with data: ', data)
    this.rewardModal = createModal(RewardModal, data)
    this.rewardModal.show()
  }
}
</script>
<style lang="scss" scoped>
@import '../../scss/breakpoints.scss';
.mynft {
  display: flex;
  flex-direction: column;
  align-items: center;
  .container {
    display: flex;
    flex-direction: column;
    width: 1440px;
    max-width: 100%;
    box-sizing: border-box;
    .wrapper{
      display: flex;
      flex-direction: row;
      justify-content: space-between;
      align-items: flex-end;
      padding: 0 4%;
      .left-bar{
        width: 40%;
      }
    }
  }
}

.mobile-top {
  display: none;
}
.page-comp{
  width: 100%;
}
.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('<desktop') {
  .container {
    flex-direction: column;
    .wrapper{
      margin-top: 80px;
      margin-bottom: -76px;
      padding: 0;
      .left-bar{
        flex-grow: 1;
        width: 50%!important;
        padding: 0 15px;
      }
    }
  }
  .searchPanel {
    width: 100%;
  }
  .filterTablet {
    padding-top: 40px;
    width: 100%;
    -webkit-transition: all 0.3s;
    transition: all 0.3s;
    height: auto;
  }
  .filterTablet.collapsed {
    padding-top: 0;
    opacity: 0;
    height: 0;
    z-index: -1;
    overflow: hidden;
  }
  .searchResult {
    padding: 2.5em 4em;
  }
  .searchResult .wrapper .btnFilter {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    text-transform: uppercase;
  }
}

@media (min-width: 1024px) and (max-width: 1439px) {
  .mynft {
    font-size: 11px;
  }
  .mynft .container {
    width: 1024px;
    max-width: 100%;
  }
}

@media (min-width: 768px) and (max-width: 1023px) {
  .mynft {
    font-size: 20px;
  }
  .container {
    width: 768px;
  }
}

@media (max-width: 767px) {
  .mynft {
    font-size: 11px;
  }
}

@media (max-width: 767px) and (max-width: 320px) {
  .mynft {
    font-size: 9px;
  }
}

@media (max-width: 767px) {
  .container {
    width: 375px;
  }
  .searchResult {
    padding: 26px 20px;
  }

  .show{
    display: flex!important;
  }
}
</style>
