<template>
  <div class="x-login-qr">
    <div class="x-login-qr__code" v-loading="loading">
      <VueQr class="x-login-qr__vqr" v-if="codeText" :text="codeText" :size="size"></VueQr>
      <div v-if="unable" class="x-login-qr__unable" @click="refresh">
        <div class="x-login-qr__wrapper">
          <XIcon class="x-login-qr__icon" name="el-icon-refresh-left"></XIcon>
          <div class="x-login-qr__action">刷新</div>
          <div class="x-login-qr__text">二维码已失效</div>
          <div class="x-login-qr__text">请刷新后重试</div>
        </div>
      </div>
    </div>
    <div class="x-login-qr__tip">{{tip}}</div>
  </div>
</template>

<script>
import VueQr from 'vue-qr';
import { uuid } from '@newpearl/utils/lib/util';
import { XIcon } from '@newpearl/ui';

export default {
  name: 'XLoginQrCode',
  inject: ['loginVm'],
  components: {
    VueQr,
    XIcon
  },
  props: {
    loginType: {
      type: String,
      default: 'weChat'
    },
    text: [String, Function],
    size: {
      type: Number,
      default: 200
    },
    tip: String,
    check: Function,
    // 二维码过期时间，单位毫秒
    expired: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      codeText: '',
      loading: false,
      uuid: null,
      counter: 0,
      unable: false,
      ticking: 0
    };
  },
  methods: {
    refresh() {
      this.proxySetText(this.text);
    },
    proxySetText(val) {
      clearTimeout(this.__TIMER__);
      this.__TIMER__ = setTimeout(() => {
        this.setText(val);
      }, 100);
    },
    setText(val) {
      if (typeof val === 'string') {
        this.codeText = val;
        return;
      }
      if (typeof val !== 'function') return;
      this.loading = true;
      this.uuid = uuid();
      this.counter = 0;
      val(this.uuid).then(text => {
        this.codeText = text;
        this.unable = false;
        this.ticking = 0;
        this.checkLogin();
      }).catch(e => {
        this.unable = true;
      }).finally(_ => {
        this.loading = false;
      });
    },
    checkLogin() {
      if (this._destroyed) return;
      if (this.unable && typeof this.check !== 'function') return;
      const { params } = this.loginVm;
      const interval = 1000;
      this.ticking += interval;
      if (this.expired > 0 && this.ticking > this.expired) {
        this.unable = true;
        return;
      }
      const query = { ...params, loginUUID: this.uuid, loginTimes: ++this.counter };
      this.check(query).then(res => {
        this.loginVm.$emit('login-success', res, this.loginType, query);
      }).catch(e => {
        if (e.code === 4) {
          this.timer = setTimeout(this.checkLogin, interval);
        } else if (e.code === 412) {
          this.unable = true;
        } else {
          this.loginVm.$emit('login-error', e, this.loginType, query);
        }
      });
    }
  },
  created() {
    this.refresh();
  },
  beforeDestroy() {
    this._destroyed = true;
    clearTimeout(this.__TIMER__);
    this.timer && clearTimeout(this.timer);
  }
};
</script>
