<template>
  <div>
    <b-alert
      variant="danger"
      :show="syncing"
    >
      <div class="alert-body">
        <span>{{ $t('dashboard.no_new_blocks') }}<strong>{{ latestTime }}</strong> </span>
      </div>
    </b-alert>

    <b-row>
      <b-col><dashboard-price-chart-2 /></b-col>
    </b-row>
    <!-- Stats Card Vertical -->
    <b-row class="match-height">
      <b-col
        xl="2"
        md="4"
        sm="6"
      >
        <dashboard-card-vertical
          icon="BoxIcon"
          :statistic="height"
          statistic-title="Height"
          color="info"
        />
      </b-col>
      <b-col
        xl="2"
        md="4"
        sm="6"
      >
        <dashboard-card-vertical
          color="warning"
          icon="DollarSignIcon"
          :statistic="supply"
          statistic-title="Total Supply"
        />
      </b-col>
      <b-col
        xl="2"
        md="4"
        sm="6"
      >
        <dashboard-card-vertical
          color="danger"
          icon="PercentIcon"
          :statistic="ratio"
          :statistic-title="`Bonded: ${bonded}`"
        />
      </b-col>
      <b-col
        xl="2"
        md="4"
        sm="6"
      >
        <dashboard-card-vertical
          color="primary"
          icon="TrendingUpIcon"
          :statistic="inflation"
          statistic-title="Inflation"
        />
      </b-col>
      <b-col
        xl="2"
        md="4"
        sm="6"
      >
        <dashboard-card-vertical
          color="success"
          icon="AwardIcon"
          :statistic="communityPool"
          statistic-title="Community Pool"
        />
      </b-col>
      <b-col
        xl="2"
        md="4"
        sm="6"
      >
        <dashboard-card-vertical
          hide-chart
          color="danger"
          icon="UserCheckIcon"
          :statistic="validators"
          statistic-title="Active Validators"
        />
      </b-col>
    </b-row>
    <b-card no-body>
      <b-card-header>
        <b-card-title>{{ $t('dashboard.active_props') }}</b-card-title>
      </b-card-header>
      <b-card-body>
        <b-row
          v-for="prop in proprosals2"
          :key="prop.id"
        >
          <b-col
            md="6"
            sm="12"
          >
            <b-media
              no-body
              class="mb-1"
            >
              <b-media-aside
                @click="showDetail(prop.id)"
              >
                <b-avatar
                  rounded
                  size="42"
                  variant="light-primary"
                >
                  {{ prop.id }}
                </b-avatar>
              </b-media-aside>
              <b-link :to="`./${chain}/gov/${prop.id}`">
                <b-media-body class="d-flex flex-column justify-content-center">
                  <h6 class="transaction-title">
                    <b-badge
                      pill
                      variant="light-primary"
                    >
                      {{ formatType(prop.contents['@type']) }}
                    </b-badge>{{ prop.title }}
                  </h6>
                  <small>will {{ caculateTallyResult(prop.tally) }}  {{ formatEnding(prop.voting_end_time) }}</small>
                </b-media-body>
              </b-link>
            </b-media>
          </b-col>
          <b-col
            md="6"
            sm="12"
          >
            <b-row>
              <b-col cols="8">
                <div class="scale">
                  <div class="box">
                    <b-progress
                      :max="totalPower? 100 * (totalPower/prop.tally.total) :100"
                      height="2rem"
                      show-progress
                      class="font-small-1"
                    >
                      <b-progress-bar
                        :id="'vote-yes'+prop.id"
                        variant="success"
                        :value="percent(prop.tally.yes)"
                        show-progress
                        :label="`${percent(prop.tally.yes).toFixed()}%`"
                      />
                      <b-progress-bar
                        :id="'vote-no'+prop.id"
                        variant="danger"
                        :value="percent(prop.tally.no)"
                        :label="`${percent(prop.tally.no).toFixed()}%`"
                        show-progress
                      />
                      <b-progress-bar
                        :id="'vote-veto'+prop.id"
                        class="bg-danger bg-darken-4"
                        :value="percent(prop.tally.veto)"
                        :label="`${percent(prop.tally.veto).toFixed()}%`"
                        show-progress
                      />
                      <b-progress-bar
                        :id="'vote-abstain'+prop.id"
                        variant="secondary"
                        :value="percent(prop.tally.abstain)"
                        :label="`${percent(prop.tally.abstain).toFixed()}%`"
                        show-progress
                      />
                    </b-progress>
                  </div>
                  <div
                    v-b-tooltip.hover
                    title="Threshold"
                    class="box overlay"
                    :style="`left:${scaleWidth(prop)}%;`"
                  />
                  <div
                    v-if="tallyParam"
                    v-b-tooltip.hover
                    title="Quorum"
                    class="box overlay"
                    :style="`left:${Number(tallyParam.quorum) * 100}%; border-color:black`"
                  />
                </div>
                <b-tooltip
                  :target="'vote-yes'+prop.id"
                >
                  {{ percent(prop.tally.yes) }}% {{ $t('dashboard.proposal_votes_yes') }}
                </b-tooltip>
                <b-tooltip
                  :target="'vote-no'+prop.id"
                >
                  {{ percent(prop.tally.no) }}% {{ $t('dashboard.proposal_votes_no') }}
                </b-tooltip>
                <b-tooltip
                  :target="'vote-veto'+prop.id"
                >
                  {{ percent(prop.tally.veto) }}% {{ $t('dashboard.proposal_votes_nwv') }}
                </b-tooltip>
                <b-tooltip
                  :target="'vote-abstain'+prop.id"
                >
                  {{ percent(prop.tally.abstain) }}% {{ $t('dashboard.proposal_votes_abstain') }}
                </b-tooltip>
              </b-col>
              <b-col
                cols="4"
                style="padding-top: 0.5em"
              >
                <b-button
                  v-b-modal.operation-modal
                  variant="primary"
                  size="sm"
                  class="mb-2"
                  @click="selectProposal('Vote',prop.id, prop.title)"
                >
                  {{ myVotes[prop.id] ? `${myVotes[prop.id]}`: 'Vote' }}
                </b-button>
              </b-col>
            </b-row>
          </b-col>
          <b-col
            cols="12"
            :class="detailId === prop.id? 'd-block': 'd-none'"
          >
            <b-card
              border-variant="primary"
              bg-variant="transparent"
              class="shadow-none"
              style="max-height:350px;overflow: auto;"
            >
              <VueMarkdown class="pb-1">
                {{ addNewLine(prop.description) }}
              </VueMarkdown>
            </b-card>
          </b-col>
        </b-row>
        <div v-if="proprosals2.length === 0">
          {{ $t('dashboard.no_active_prop') }}
          <b-link :to="`./${chain}/gov`">
            {{ $t('dashboard.browse') }}
          </b-link>
        </div>
      </b-card-body>
    </b-card>
    <b-card
      border-variant="primary"
      bg-variant="transparent"
      class="shadow-none"
    >
      <b-card-title class="d-flex justify-content-between text-capitalize">
        <span>{{ walletName }} {{ $t('dashboard.assets') }} </span>
        <small>
          <b-link
            v-if="address"
            :to="`./${chain}/account/${address}`"
          >
            {{ $t('dashboard.more') }}
          </b-link>
          <b-link
            v-else
            :to="`/wallet/accounts`"
          >
            {{ $t('dashboard.not_conn') }}
          </b-link>
        </small>
      </b-card-title>
      <b-row>
        <b-col
          lg="3"
          sm="6"
        >
          <dashboard-card-horizontal
            icon="DollarSignIcon"
            color="success"
            :statistic="walletBalances"
            statistic-title="Balances"
          />
        </b-col>
        <b-col
          lg="3"
          sm="6"
        >
          <dashboard-card-horizontal
            icon="LockIcon"
            :statistic="walletStaking"
            statistic-title="Staking"
          />
        </b-col>
        <b-col
          lg="3"
          sm="6"
        >
          <dashboard-card-horizontal
            icon="ArrowUpCircleIcon"
            color="info"
            :statistic="walletRewards"
            statistic-title="Rewards"
          />
        </b-col>
        <b-col
          lg="3"
          sm="6"
        >
          <dashboard-card-horizontal
            icon="UnlockIcon"
            color="danger"

            :statistic="walletUnbonding"
            statistic-title="Unbonding"
          />
        </b-col>
      </b-row>
      <b-row v-if="stakingList && stakingList.length > 0">
        <b-col>
          <b-card no-body>
            <b-table
              :items="stakingList"
              :fields="fields"
              striped
              hover
              responsive="sm"
              stacked="sm"
            >
              <template #cell(action)="data">
                <!-- size -->
                <b-button-group
                  size="sm"
                  class="d-none"
                >
                  <b-button
                    v-b-modal.operation-modal
                    v-ripple.400="'rgba(113, 102, 240, 0.15)'"
                    v-b-tooltip.hover.top="'Delegate'"
                    variant="outline-primary"
                    @click="selectDelegation(data,'Delegate')"
                  >
                    <feather-icon icon="LogInIcon" />
                  </b-button>
                  <b-button
                    v-b-modal.operation-modal
                    v-ripple.400="'rgba(113, 102, 240, 0.15)'"
                    v-b-tooltip.hover.top="'Redelegate'"
                    variant="outline-primary"
                    @click="selectDelegation(data,'Redelegate')"
                  >
                    <feather-icon icon="ShuffleIcon" />
                  </b-button>
                  <b-button
                    v-b-modal.operation-modal
                    v-ripple.400="'rgba(113, 102, 240, 0.15)'"
                    v-b-tooltip.hover.top="'Unbond'"
                    variant="outline-primary"
                    @click="selectDelegation(data,'Unbond')"
                  >
                    <feather-icon icon="LogOutIcon" />
                  </b-button>
                </b-button-group>
                <b-dropdown
                  v-b-modal.operation-modal
                  split
                  variant="outline-primary"
                  text="Delegate"
                  class="mr-1"
                  size="sm"
                  @click="selectDelegation(data,'Delegate')"
                >
                  <template #button-content>
                    {{ $t('dashboard.delegate') }}
                  </template>
                  <b-dropdown-item
                    v-b-modal.operation-modal
                    @click="selectDelegation(data,'Redelegate')"
                  >
                    {{ $t('dashboard.redelegate') }}
                  </b-dropdown-item>
                  <b-dropdown-item
                    v-b-modal.operation-modal
                    @click="selectDelegation(data,'Unbond')"
                  >
                    {{ $t('dashboard.unbond') }}
                  </b-dropdown-item>
                </b-dropdown>
                <b-button
                  v-b-modal.operation-modal
                  variant="outline-primary"
                  size="sm"
                  @click="selectWithdraw()"
                >
                  {{ $t('dashboard.withdraw_reward') }}
                </b-button>
              </template>
            </b-table>
          </b-card>
        </b-col>
      </b-row>

      <b-row v-if="unbonding && unbonding.length > 0">
        <b-col>
          <b-card>
            <b-card-header class="pt-0 pl-0 pr-0">
              <b-card-title>{{ $t('dashboard.unbonding_token') }}</b-card-title>
            </b-card-header>
            <b-card-body class="pl-0 pr-0">
              <b-row
                v-for="item in unbonding"
                :key="item.validator_address"
              >
                <b-col cols="12">
                  <span class="font-weight-bolder">From: <router-link :to="`../staking/${item.validator_address}`">{{ item.validator_address }}</router-link></span>
                </b-col>
                <b-col cols="12">
                  <b-table
                    :items="item.entries"
                    class="mt-1"
                    striped
                    hover
                    responsive="sm"
                    stacked="sm"
                  >
                    <template #cell(completion_time)="data">
                      {{ formatDate(data.item.completion_time) }}
                    </template>
                    <template #cell(initial_balance)="data">
                      {{ data.item.initial_balance }}
                    </template>
                    <template #cell(balance)="data">
                      {{ data.item.balance }}
                    </template>
                  </b-table>
                </b-col>
              </b-row>
            </b-card-body>
          </b-card>
        </b-col>
      </b-row>
      <b-row
        v-if="address"
        class="mt-1"
      >
        <b-col cols="6">
          <b-button
            v-b-modal.operation-modal
            block
            variant="success"
            @click="selectSend()"
          >
            <feather-icon icon="SendIcon" />
            {{ $t('dashboard.send') }}
          </b-button>
        </b-col>
        <b-col cols="6">
          <b-button
            block
            variant="info"
            :to="`${chain}/account/${address}/receive`"
          >
            <feather-icon
              icon="PlusCircleIcon"
            />
            {{ $t('dashboard.receive') }}
          </b-button>
        </b-col>
      </b-row>
    </b-card>
    <router-link to="/wallet/import">
      <b-card class="addzone text-center">
        <feather-icon icon="PlusIcon" />
        {{ $t('dashboard.connect_wal') }}
      </b-card>
    </router-link>
    <operation-modal
      :address="address"
      :validator-address="selectedValidator"
      :type="operationModalType"
      :proposal-id="selectedProposalId"
      :proposal-title="selectedTitle"
    />
    <div id="txevent" />
  </div>
</template>

<script>
import {
  BRow, BCol, BAlert, BCard, BTable, BFormCheckbox, BCardHeader, BCardTitle, BMedia, BMediaAside, BMediaBody, BAvatar,
  BCardBody, BLink, BButtonGroup, BButton, BTooltip, VBModal, VBTooltip, BCardFooter, BProgress, BProgressBar, BBadge,
  BDropdown, BDropdownItem,
} from 'bootstrap-vue'
import {
  formatNumber, formatTokenAmount, isToken, percent, timeIn, toDay, toDuration, tokenFormatter, getLocalAccounts,
  getStakingValidatorOperator, formatToken,
} from '@/libs/utils'
import OperationModal from '@/views/components/OperationModal/index.vue'
import Ripple from 'vue-ripple-directive'
import dayjs from 'dayjs'
import VueMarkdown from 'vue-markdown'
import ParametersModuleComponent from './components/parameters/ParametersModuleComponent.vue'
import DashboardCardHorizontal from './components/dashboard/DashboardCardHorizontal.vue'
import DashboardCardVertical from './components/dashboard/DashboardCardVertical.vue'
import DashboardPriceChart2 from './components/dashboard/DashboardPriceChart2.vue'
import FeatherIcon from '../@core/components/feather-icon/FeatherIcon.vue'

export default {
  components: {
    BAvatar,
    BButtonGroup,
    BTooltip,
    BButton,
    BDropdown,
    BDropdownItem,
    BRow,
    BCol,
    BAlert,
    BCard,
    BTable,
    BFormCheckbox,
    BCardHeader,
    BCardTitle,
    BMediaBody,
    BMediaAside,
    BMedia,
    BCardBody,
    BLink,
    BCardFooter,
    BProgress,
    BProgressBar,
    VueMarkdown,
    BBadge,

    OperationModal,
    ParametersModuleComponent,
    DashboardCardHorizontal,
    DashboardPriceChart2,
    DashboardCardVertical,
    FeatherIcon,
  },
  directives: {
    'b-modal': VBModal,
    'b-tooltip': VBTooltip,
    Ripple,
  },
  data() {
    return {
      detailId: 0,
      fields: ['validator', 'delegation', 'rewards', 'action'],
      delegations: [],
      rewards: [],
      unbonding: [],
      chain: this.$store.state.chains.selected.chain_name,
      syncing: false,
      latestTime: '',
      marketData: null,
      height: '-',
      supply: '-',
      bonded: '-',
      validators: '-',
      communityPool: '-',
      ratio: '-',
      inflation: '-',
      proposals: [],
      myVotes: {},
      selectedValidator: '',
      selectedProposalId: 0,
      selectedTitle: '',
      operationModalType: '',
      tallyParam: null,
      totalPower: 0,
      voteColors: {
        YES: 'success',
        NO: 'warning',
        ABSTAIN: 'info',
        NO_WITH_VETO: 'danger',
      },

      walletBalances: '-',
      walletStaking: '-',
      walletRewards: '-',
      walletUnbonding: '-',
      address: null,

    }
  },
  computed: {
    walletName() {
      const key = this.$store?.state?.chains?.defaultWallet
      if (key) {
        const accounts = getLocalAccounts() || {}
        const account = Object.entries(accounts)
          .map(v => ({ wallet: v[0], address: v[1].address.find(x => x.chain === this.$store.state.chains.selected.chain_name) }))
          .filter(v => v.address)
          .find(x => x.wallet === key)
        if (account) {
          this.fetchAccount(account.address.addr)
        }
      }
      return key || 'Wallet'
    },
    proprosals2() {
      return this.proposals
    },
    stakingList() {
      return this.delegations.map(x => {
        const rewards = this.rewards.find(r => r.validator_address === x.delegation.validator_address)
        const conf = this.$http.getSelectedConfig()
        const decimal = conf.assets[0].exponent || '6'
        return {
          valAddress: x.delegation.validator_address,
          validator: getStakingValidatorOperator(this.$store.state.chains.selected.chain_name, x.delegation.validator_address),
          delegation: formatToken(x.balance, {}, decimal),
          rewards: rewards ? this.formatToken(rewards.reward) : '',
          action: '',
        }
      })
    },
  },
  created() {
    this.$http.getStakingParameters().then(res => {
      Promise.all([this.$http.getStakingPool(), this.$http.getBankTotal(res.bond_denom)])
        .then(pool => {
          this.supply = `${formatNumber(formatTokenAmount(pool[1].amount, 2, res.bond_denom, false), true, 2)}`
          this.bonded = `${formatNumber(formatTokenAmount(pool[0].bondedToken, 2, res.bond_denom, false), true, 2)}`
          this.ratio = `${percent(pool[0].bondedToken / pool[1].amount)}%`
          this.totalPower = pool[0].bondedToken
        })
    })

    this.$http.getGovernanceListByStatus(2).then(gov => {
      this.proposals = gov.proposals
      this.proposals.forEach(p => {
        this.$http.getGovernanceTally(p.id, 0).then(update => {
          // const p2 = p
          // p2.tally = update
          // this.proposals.push(p2)
          // this.proposals.sort((a, b) => a.id - b.id)
          this.$set(p, 'tally', update)
        })
      })
    })

    this.$http.getLatestBlock().then(res => {
      this.height = res.block.header.height
      if (timeIn(res.block.header.time, 3, 'm')) {
        this.syncing = true
      } else {
        this.syncing = false
      }
      this.latestTime = toDay(res.block.header.time, 'long')
      this.validators = res.block.last_commit.signatures.length
    })

    this.$http.getCommunityPool().then(res => {
      this.communityPool = this.formatToken(res.pool)
    })

    this.$http.getGovernanceParameterTallying().then(res => {
      this.tallyParam = res
    })

    const conf = this.$http.getSelectedConfig()
    if (conf.excludes && conf.excludes.indexOf('mint') > -1) {
      this.inflation = '-'
    } else {
      this.$http.getMintingInflation().then(res => {
        this.inflation = `${percent(res)}%`
      }).catch(() => {
        this.inflation = '-'
      })
    }
  },
  mounted() {
    const elem = document.getElementById('txevent')
    elem.addEventListener('txcompleted', () => {
      const key = this.$store?.state?.chains?.defaultWallet
      if (key) {
        const accounts = getLocalAccounts() || {}
        const account = Object.entries(accounts)
          .map(v => ({ wallet: v[0], address: v[1].address.find(x => x.chain === this.$store.state.chains.selected.chain_name) }))
          .filter(v => v.address)
          .find(x => x.wallet === key)
        if (account) {
          this.fetchAccount(account.address.addr)
        }
      }
    })
  },
  methods: {
    caculateTallyResult(tally) {
      if (this.tallyParam && tally && this.totalPower > 0) {
        if (tally.veto < Number(this.tallyParam.veto_threshold)
        && tally.yes > Number(this.tallyParam.threshold)
        && tally.total / this.totalPower > Number(this.tallyParam.quorum)) {
          return 'pass'
        }
      }
      return 'be rejected'
    },
    scaleWidth(p) {
      if (this.tallyParam) {
        return Number(this.tallyParam.quorum) * Number(this.tallyParam.threshold) * (1 - p.tally.abstain) * 100
      }
      return 50
    },
    selectProposal(modal, pid, title) {
      this.operationModalType = modal
      this.selectedProposalId = Number(pid)
      this.selectedTitle = title
    },
    selectDelegation(v, type) {
      this.selectedValidator = v.item.valAddress
      this.operationModalType = type
    },
    selectSend() {
      this.operationModalType = 'Transfer'
    },
    selectWithdraw() {
      this.operationModalType = 'Withdraw'
    },
    formatToken(tokens) {
      if (Array.isArray(tokens)) {
        let nativeToken = tokens.filter(x => x.denom.length < 11)
        if (tokens.length > 1) {
          const sum = {}
          const reduce = nativeToken.reduce((b, a) => {
            const b2 = b
            if (b2[a.denom]) {
              b2[a.denom] += Number(a.amount)
            } else {
              b2[a.denom] = Number(a.amount)
            }
            return b2
          }, sum)
          nativeToken = Object.keys(reduce).map(k => ({ denom: k, amount: reduce[k] }))
        }
        return tokenFormatter(nativeToken, {}, 0)
      }
      return '-'
    },
    fetchAccount(address) {
      this.address = address
      this.$http.getBankAccountBalance(address).then(bal => {
        this.walletBalances = this.formatToken(bal)
      })
      this.$http.getStakingReward(address).then(res => {
        this.rewards = res.rewards
        this.walletRewards = this.formatToken(res.rewards.map(x => x.reward).flat())
      })
      this.$http.getStakingDelegations(address).then(res => {
        const delegations = res.delegation_responses || res
        this.delegations = delegations
        this.walletStaking = this.formatToken(delegations.map(x => x.balance).flat())
      })
      this.$http.getStakingUnbonding(address).then(res => {
        const token = this.$store.state.chains.selected.assets[0]
        if (token) {
          const newTokens = []
          const denom = token.base
          const unbonding = res.unbonding_responses || res
          this.unbonding = unbonding
          unbonding.forEach(x => {
            x.entries.forEach(y => {
              newTokens.push({
                amount: y.balance,
                denom,
              })
            })
          })
          if (newTokens.length > 0) {
            this.walletUnbonding = this.formatToken(newTokens)
          }
        }
      })
      this.proposals.forEach(x => {
        this.$http.getGovernanceProposalVote(x.id, address, null)
          .then(v => {
            this.myVotes[x.id] = this.formatVoteOption(v.vote.option)
          })
          .catch(() => {
            this.myVotes[x.id] = null
          })
      })
    },
    formatVoteOption(v) {
      return v.replaceAll('VOTE_OPTION_', '')
    },
    formatEnding(v) {
      return toDay(v, 'from')
    },
    formatType(v) {
      const txt = String(v).replace('Proposal', '')
      const index = txt.lastIndexOf('.')
      return index > 0 ? txt.substring(index + 1) : txt
    },
    normalize(data, title) {
      if (!data) return null
      const items = this.makeItems(data)
      return {
        title,
        items,
      }
    },
    makeItems(data) {
      return Object.keys(data).map(k => {
        if (isToken(data[k])) {
          return { title: tokenFormatter(data[k]), subtitle: k }
        }
        if (typeof data[k] === 'boolean') {
          return { title: data[k], subtitle: k }
        }
        return { title: this.convert(data[k]), subtitle: k }
      })
    },
    addNewLine(value) {
      return value ? value.replace(/(?:\\[rn])+/g, '\n') : '-'
    },
    percent: v => percent(v),
    processBarLength(v) {
      return percent(v)
    },
    formatDate: v => dayjs(v).format('YYYY-MM-DD HH:mm:ss'),
    convert(v) {
      if (typeof v === 'object') {
        const v2 = {}
        Object.entries(v).forEach(e => {
          const k = e[0]
          const x = e[1]
          v2[k] = this.convert(x)
        })
        return v2
      }
      const d = parseFloat(v)
      if (d === 0) return '0'
      if (d < 1.01) {
        return `${percent(d)}%`
      }
      if (d > 1000000000) {
        return `${toDuration(d / 1000000)}`
      }
      if (d > 0) {
        return d.toFixed()
      }
      return v
    },
    showDetail(id) {
      if (this.detailId !== id) {
        this.detailId = id
      } else {
        this.detailId = 0
      }
    },
  },
}
</script>

<style>
.addzone {
    border: 2px dashed #ced4da;
    background: #fff;
    border-radius: 6px;
    cursor: pointer;
    box-shadow: none;
}
.addzone :hover {
    border: 2px dashed #7367F0;
}
</style>
