import api from '@/api'
import { showError, getUrlParam, getMeechatType, openBlankWindow, getUserOpt, setUserOpt, getShowLoginTyps } from '@/util/util'
import { mapActions, mapState, mapMutations } from 'vuex'
import ScatterJS from 'scatterjs-core'
import EthHelper from '@/util/ethHelper.js'
import TronHelper from '@/util/tronHelper.js'
import { Message } from 'element-ui'
import PostMessager from '@/util/postMessager.js'
import { getNetwork } from '@/util/contract.js'

let _timeoutHandler = 0 // 轮询定时器

// 账号登录
export const accountLoginMixin = {
  data () {
    return {
      showLoginTypes: getShowLoginTyps(),
      curLoginType: '', // 当前登录类型[eos,eth,telegram,eth,tron]
      winHandler: null, // 新开窗口
      winTimer: null, // 检测窗口定时器
      meechatType: getMeechatType(),
      from: decodeURIComponent(getUrlParam('from'))
    }
  },
  computed: {
    ...mapState(['isLogining', 'account', 'scatter'])
  },
  methods: {
    ...mapMutations(['setLogining']),
    ...mapActions([
      'setScatter',
      'setAccount',
      'doScatterLogin',
      'doContractLogin',
      'initSocket'
    ]),
    /**
     * @des 校验本地登录态
    */
    async checkLocalLogin () {
      this.setLogining(true)

      let userId = localStorage.getItem('user_id')
      let token = localStorage.getItem('token')

      if (!userId || !token) {
        this.setLogining(false)
        return false
      }

      let { data } = await api.user.checkLocalLogin({
        user_id: userId,
        token: token
      })

      if (data.data.is_login) {
        this.curLoginType = getUserOpt('loginType') || 'eos'

        if ((this.curLoginType == 'eos' || this.curLoginType == 'meetone')) {
          if (top === self) {
            await this.loginEosMeetoneCommon(this.curLoginType)
          } else {
            await this.loginEosMeetoneParent(this.curLoginType, true)
          }
          this.setLogining(false)
        } else {
          this.loginSuccCallBack({
            userId: userId,
            token: token
          })
        }

        return true
      } else {
        localStorage.clear()
        this.setLogining(false)

        return false
      }
    },
    /**
     * @des 调用父级页面getIdentity
    */
    async getParentIdentity () {
      return new Promise((resolve) => {
        setTimeout(async () => {
          try {
            let networkConfig = await getNetwork()
            let response = await this.postMessager.send({ action: 'meechat:getIdentity', data: { network: networkConfig, eosType: this.curLoginType } })
            let account = response.accounts.find(x => x.blockchain === 'eos')

            localStorage.setItem('account', JSON.stringify(account))
            this.setAccount(account)
          } catch (error) {
            this.setLogining(false)
          }
          resolve()
        }, 1000)
      })
    },
    /**
     * @des 内嵌版调用父级eos登录
     * */
    async loginEosMeetoneParent (loginType, isAutoLogin) {
      this.curLoginType = loginType
      setUserOpt('eosType', this.curLoginType)
      this.setLogining(true)
      try {
        // scatter登录
        await this.getParentIdentity(isAutoLogin)
        if (!this.account) return
        // 合约登录
        let ctLoginRes = await this.doContractLogin()

        this.loginSuccCallBack({
          userId: ctLoginRes.data ? ctLoginRes.data.user_id : ctLoginRes.user_id,
          token: ctLoginRes.data ? ctLoginRes.data.token : ctLoginRes.token
        })
        location.href.replace('show=false', 'show=true')
      } catch (msg) {
        if (msg.type) {
          // scatter报错的情况
        } else {
          try {
            let json = JSON.parse(msg)
            let details = json.error.details
            Message({
              message: details[0].message,
              type: 'error'
            })
          } catch (e) {
            Message({
              message: 'Try Again',
              type: 'error'
            })
          }
        }
        this.showLoginBtn = true
        this.setLogining(false)
      }
    },
    /**
     * @des eos,Meetone登录流程一样，合约不一样
     * @param {String} loginType 登录类型
     */
    async loginEosMeetoneCommon (loginType) {
      this.curLoginType = loginType

      return new Promise(async (resolve, reject) => {
        this.setLogining(true)
        let eosType = getUserOpt('eosType')
        let connected = await this.connectScatterJS()
        if (connected) {
          if (eosType && eosType != this.curLoginType) {
            this.scatter.logout && this.scatter.logout()
          }

          setUserOpt('eosType', this.curLoginType)

          try {
            // 调起scatter授权登录

            await this.doScatterLogin(this.$router)

            if (this.meechatType == 'mini') {
              localStorage.setItem('account', JSON.stringify(this.account))
            }

            // 签名登录
            try {
              let ctLoginRes = await this.doContractLogin(2)

              this.loginSuccCallBack({
                userId: ctLoginRes.data ? ctLoginRes.data.user_id : ctLoginRes.user_id,
                token: ctLoginRes.data ? ctLoginRes.data.token : ctLoginRes.token
              })
            } catch (e) {
              reject(e)
              let err = e
              if (typeof e == 'string') {
                err = JSON.parse(e)
              }
              if (err.code >= 500) {
                showError(err.error.what)
              } else if (err.code >= 400) {
                showError(this.$t('login.loginForSecurity'))
              }

              this.$store.commit('setAccount', '')
              await (ScatterJS.scatter && ScatterJS.scatter.identity && ScatterJS.scatter.logout && ScatterJS.scatter.logout())
            }
          } catch (error) {
            this.$store.commit('setAccount', '')
            reject(error)
            if (this.meechatType == 'mini') {
              this.showLoginBtn = true
            } else if (this.isLogining) {
              this.$router.replace('/login')
              this.$store.commit('chatAppLogin', false)
            }
          }
          this.setLogining(false)
        } else {
          if (this.meechatType == 'mini') {
            this.showLoginBtn = true
          } else if (this.isLogining) {
            this.$router.replace('/login')
          }

          if (this.isLogining && !localStorage.getItem('user_id')) {
            // 用户scatter未解锁
            showError(this.$t('login.installScatter'), 'Scatter')
          }

          this.setAccount('')
          this.setLogining(false)
        }
        resolve()
      })
    },
    connectScatterJS () {
      if (this.scatter) return Promise.resolve(true)

      // 连接scatter
      return new Promise((resolve, reject) => {
        ScatterJS.scatter.connect('MEE_CHAT').then(async connected => {
          if (connected) {
            // 设置scatter
            this.setScatter(ScatterJS.scatter)

            // 清空全局scatter引用
            window.ScatterJS = null
            resolve(true)
          } else {
            resolve(false)
          }
        }).catch(e => {
          this.setLogining(false)
          reject(e)
        })
      })
    },
    /**
     * @des Eth登录 MetaMask
     */
    async loginEth () {
      this.curLoginType = 'eth'
      this.setLogining(true)
      try {
        let { account, sign } = await EthHelper.initEth()
        let { data } = await api.user.ethLogin({
          account: account,
          sign: sign
        })
        this.loginSuccCallBack({
          userId: data.data.user_id,
          token: data.data.token
        })
      } catch (e) {
        this.setLogining(false)
      }
    },
    /**
     * @des Tron登录 TronLink
     */
    async loginTron () {
      this.curLoginType = 'tron'
      this.setLogining(true)

      try {
        let { account, sign } = await TronHelper.initTron()
        let { data } = await api.user.tronLogin({
          account: account,
          sign: sign
        })

        this.loginSuccCallBack({
          userId: data.data.user_id,
          token: data.data.token
        })
      } catch (e) {
        this.setLogining(false)
      }
    },
    /**
     * @des SimpleWallet登录
    */
    loginSimpleWallet () {
      this.curLoginType = 'simplewallet'
      let param = {
        protocol: 'SimpleWallet',
        version: '1.0',
        dappName: 'MeeChat',
        dappIcon: 'https://static.meechat.me/cdn/mee.chat/dist/img/icons/meechat_icon.png',
        action: 'login',
        uuID: Math.random(),
        loginUrl: location.origin + '/user/simplewallet'
      }

      let url = `simplewallet://eos.io?param=` + JSON.stringify(param)
      this.winHandler = openBlankWindow(url)
      this.loginCheck(param.uuID, 0)
    },
    /**
     * @des Telegram登录
     */
    async loginTelegram () {
      this.curLoginType = 'telegram'
      this.winHandler = openBlankWindow('')

      let { data } = await api.user.tgCSRF({
        type: 'login'
      })

      this.winHandler.location.href = data.data.url

      this.loginCheck(data.data.csrf_token)
    },
    /**
     * @des 轮询校验登录
     * @param {*} uuID
     * @param {Number} times 轮询次数
     * @param {String} 登录类型[eos,eth,telegram]
     */
    async loginCheck (uuID, times) {
      if (times === 0) {
        // 第一次调用
        clearTimeout(_timeoutHandler)
      } else if (times >= 60) {
        return false
      }

      let res = {}
      let isLoginSuccess = false // 是否登录成功
      let isLoginCheck = true // 是否继续校验
      try {
        if (this.curLoginType == 'simplewallet') {
          // 校验eth
          res = await api.user.simplewalletCheck({ uuID })
          isLoginSuccess = res.data && res.data.result === 1
        } else if (this.curLoginType == 'telegram') {
          // 校验telegram
          res = await api.user.tgLogin2({ csrf_token: uuID })
          isLoginSuccess = res.data && res.data.data && res.data.data.status > 0
          isLoginCheck = (this.winHandler != null) || (res.data && res.data.status == 0)
        }
      } catch (ex) {
      }

      if (isLoginSuccess) {
        this.loginSuccCallBack({
          userId: res.data.data.user_id,
          token: res.data.data.token
        })

        if (this.winHandler != null) {
          this.winHandler.close()
          this.winHandler = null
        }
        return Promise.resolve(res.data)
      } else if (isLoginCheck) {
        // 定时检查是否登录成功
        _timeoutHandler = setTimeout(() => {
          this.loginCheck(uuID, ++times)
        }, 1000)
      }
    },
    async loginSuccCallBack ({ userId = null, token = null }) {
      this.setLogining(false)

      setUserOpt('loginType', this.curLoginType)
      if (userId) {
        this.$store.commit('setUserId', userId)
        localStorage.setItem('user_id', userId)
      }
      if (token) {
        this.$store.commit('setToken', token)
        localStorage.setItem('token', token)
      }

      switch (this.meechatType) {
        // 内嵌版
        case 'mini':
          this.$emit('initMiniLoginCallback')
          break
        // h5版本,完整版
        case 'h5':
        case 'pc':
          if (this.meechatType === 'h5' && this.$route.name === 'login') {
            let url = this.from && this.from != 'null' ? this.from : `/`
            this.$router.replace(url)
          }

          await this.initSocket()
          this.$store.commit('chatAppLogin', true)
          this.$store.commit('toApp', true)
          break
      }
    }
  },
  mounted () {
    // 内嵌版-初始化postMessage消息管理器
    if (top != self) {
      let callback = (event) => {
        if (event.action === 'meechat:setShow') {
          this.handleToggleChat(event.show)
        } else if (event.action === 'meechat:logout') {
          this.handleLogout2()
        }
      }

      this.postMessager = new PostMessager('*', { callback })
      window.postMessager = this.postMessager
    }
  }
}
