<template>
  <ElCard :class="['x-login',`x-login-${_uid}`]" :style="styles">
    <template v-if="!showForgetPassword">
      <Switcher v-if="switchable" :type.sync="tabsGroup"></Switcher>
      <div v-if="isShowLogo" class="x-login__logo">
        <slot name="logo"></slot>
      </div>
      <ElTabs v-if="isUserTabs" v-model="currentTab" :class="tabClass">
        <ElTabPane v-if="hasType('password')" lazy name="password" :label="texts.passwordTabLabel">
          <PasswordLogin></PasswordLogin>
        </ElTabPane>
        <ElTabPane v-if="hasType('sms')" lazy name="sms" :label="texts.smsTabLabel">
          <SmsLogin ref="smsLogin"></SmsLogin>
        </ElTabPane>
      </ElTabs>
      <ElTabs v-if="isQrCodeTabs" v-model="currentTab" class="x-login__tabs">
        <ElTabPane v-if="hasType('mzApp')" lazy name="mzApp" :label="texts.mzAppTabLabel">
          <QrCodeLogin v-if="currentTab==='mzApp'"
                       login-type="mzApp"
                       :expired="qrCodeExpired"
                       :text="mzAppQrCode"
                       :check="checkMzAppLogin"
                       :tip="texts.mzAppTip"></QrCodeLogin>
        </ElTabPane>
        <ElTabPane v-if="hasType('weChat')" lazy name="weChat" :label="texts.weChatTabLabel">
          <QrCodeLogin v-if="currentTab==='weChat'"
                       login-type="weChat"
                       :expired="qrCodeExpired"
                       :text="weChatQrCode"
                       :check="checkWeChatLogin"
                       :tip="texts.weChatTip"></QrCodeLogin>
        </ElTabPane>
      </ElTabs>
    </template>
    <ForgetPassword v-if="showForgetPassword"></ForgetPassword>
  </ElCard>
</template>

<script>
/**
 * XLogin 登录组件
 * @module XLogin
 */
import {
  Card as ElCard,
  Tabs as ElTabs,
  TabPane as ElTabPane, Notification
} from 'element-ui';
import Switcher from './components/Switcher';
import PasswordLogin from './components/PasswordLogin';
import SmsLogin from './components/SmsLogin';
import QrCodeLogin from './components/QrCodeLogin';
import ForgetPassword from './components/ForgetPassword';
import { pick } from '@newpearl/utils/lib/util';
import { injectStyle } from '@newpearl/utils/lib/dom';
import createStyle from './createStyle';

const defaultTextConfig = {
  passwordTabLabel: '密码登录',
  smsTabLabel: '短信登录',
  weChatTabLabel: '微信二维码登录',
  usernamePlaceholder: '请输入手机号/用户名',
  usernameForSmsPlaceholder: '请输入手机号',
  passwordPlaceholder: '请输入密码',
  forgetPassword: '忘记密码？',
  smsCodePlaceholder: '请输入验证码',
  smsCodeButtonText: '获取验证码',
  imageCodePlaceholder: '请输入图形验证码',
  submitButtonText: '登录',
  weChatTip: '请使用微信扫码登录',
  mzAppTabLabel: '明珠家二维码登录',
  mzAppTip: '请使用明珠家扫码登录'
};

const LOGIN_TYPES = ['weChat', 'password', 'sms', 'mzApp'];
const TABS_GROUP = {
  user: ['password', 'sms'],
  qrCode: ['mzApp', 'weChat']
};
/**
 * 插槽
 * @member slots
 * @property {string} logo 定义logo内容
 */
export default {
  name: 'XLogin',
  components: {
    ElCard,
    Switcher,
    ElTabs,
    ElTabPane,
    PasswordLogin,
    SmsLogin,
    QrCodeLogin,
    ForgetPassword
  },
  provide() {
    return {
      loginVm: this
    };
  },
  /**
   * 属性参数
   * @member props
   * @property {string} [size=medium] 输入框尺寸，可选 default/medium/small/mini
   * @property {string} [width=360px] 宽度
   * @property {string} [height=auto] 高度
   * @property {string[]} [loginTypes] 登录方式: weChat 微信扫码 / password 密码 / sms 短信 / mzApp 明珠家app
   * @property {string} [defaultType] 默认登录方式: weChat 微信扫码 / password 密码 / sms 短信
   * @property {function} [login] 登录接口函数，需要返回Promise
   * @property {string|function} [verify=/api/verifyImage.jpg] 图形验证码接口
   * @property {function} [sendSmsCode]  发送短信验证码接口
   * @property {function} [checkSmsCode] 校验短信验证码接口
   * @property {function} [weChatQrCode] 获取微信登录二维码内容
   * @property {function} [checkWeChatLogin] 校验微信是否登录
   * @property {number} [qrCodeExpired=0] 二维码过期时间, 0标识不限制
   * @property {function} [mzAppQrCode] 明珠家app二维码内容
   * @property {function} [checkMzAppLogin] 校验明珠家ap是否登录
   * @property {string} [color] 颜色
   * @property {function} [resetPasswordMethod] 重置密码接口
   * @property {boolean} [supportResetPassword=true] 开启重置密码功能
   */
  props: {
    size: {
      type: String,
      default: 'medium'
    },
    width: {
      type: String,
      default: '360px'
    },
    height: {
      type: String,
      default: 'auto'
    },
    // 登录方式: weChat 微信扫码 / password 密码 / sms 短信 / mzApp 明珠家app
    loginTypes: {
      type: Array,
      default() {
        return LOGIN_TYPES;
      }
    },
    // 默认登录方式: weChat 微信扫码 / password 密码 / sms 短信
    defaultType: {
      type: String,
      default: 'password',
      validator(val) {
        return LOGIN_TYPES.includes(val);
      }
    },
    // 文本配置
    textConfig: {
      type: Object,
      default() {
        return Object.create(null);
      }
    },
    // 登录附加数据
    params: {
      type: Object,
      default() {
        return Object.create(null);
      }
    },
    // 登录回调方法
    login: Function,
    // 获取验证码接口地址
    verify: {
      type: [String, Function],
      default: '/api/user/verifyImage.jpg'
    },
    // 发送短信验证码接口
    sendSmsCode: Function,
    // 校验短信验证码接口
    checkSmsCode: Function,
    // 获取微信登录二维码内容
    weChatQrCode: Function,
    // 校验微信是否登录
    checkWeChatLogin: Function,
    // 二维码过期时间
    qrCodeExpired: {
      type: Number,
      default: 0
    },
    // 明珠家app二维码内容
    mzAppQrCode: Function,
    // 校验明珠家ap是否登录
    checkMzAppLogin: Function,
    // 颜色
    color: String,
    // 重置密码
    resetPasswordMethod: Function,
    supportResetPassword: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      tabsGroup: 'user',
      currentTab: this.defaultType,
      loading: false,
      username: '',
      showForgetPassword: false
    };
  },
  computed: {
    isUserTabs() {
      return this.tabsGroup === 'user';
    },
    isQrCodeTabs() {
      return this.tabsGroup === 'qrCode';
    },
    texts() {
      return {
        ...defaultTextConfig,
        ...this.textConfig
      };
    },
    styles() {
      return {
        width: this.width,
        height: this.height
      };
    },
    isShowLogo() {
      return this.$slots.logo && this.tabsGroup === 'user';
    },
    tabClass() {
      return {
        'x-login__tabs': true,
        'x-login__tabs--logo': this.isShowLogo
      };
    },
    switchable() {
      if (this.loginTypes > 2) return true;
      let user, qrCode;
      for (let i = 0, len = this.loginTypes.length; i < len; i++) {
        const type = this.loginTypes[i];
        if (TABS_GROUP.user.includes(type)) {
          user = true;
        }
        if (TABS_GROUP.qrCode.includes(type)) {
          qrCode = true;
        }
        if (user && qrCode) {
          break;
        }
      }
      return user && qrCode;
    }
  },
  watch: {
    tabsGroup(name) {
      const group = TABS_GROUP[name];
      let tab = '';
      for (let i = 0; i < group.length; i++) {
        if (this.loginTypes.includes(group[i])) {
          tab = group[i];
          break;
        }
      }
      this.currentTab = tab;
    },
    defaultType: {
      immediate: true,
      handler(val) {
        Object.keys(TABS_GROUP).forEach(name => {
          if (TABS_GROUP[name].includes(val)) {
            this.tabsGroup = name;
            this.$nextTick(() => {
              this.currentTab = val;
            });
          }
        });
      }
    }
  },
  methods: {
    hasType(name) {
      return this.loginTypes.includes(name);
    },
    userLogin({ username, password, msgCode = '', loginType = 'password' }) {
      const { params, login } = this;
      const query = pick({
        ...params,
        username,
        password,
        msgCode,
        loginType
      });
      if (login) {
        this.loading = true;
        login(query).then(res => {
          /**
           * 登录成功
           * @event login-success
           * @param {object} res 接口响应的数据
           * @param {string} loginType 登录方式
           * @param {object} query 传递给登录接口的参数对象
           */
          this.$emit('login-success', res, loginType, query);
          return res;
        }).catch(e => {
          const msg = e.msg || e.message || '未知错误';
          Notification({
            message: msg,
            type: 'warning'
          });
          /**
           * 登录失败
           * @event login-error
           * @param {object} e 错误信息对象
           * @param {string} loginType 登录方式
           * @param {object} query 传递给登录接口的参数对象
           */
          this.$emit('login-error', e, loginType, query);
        }).finally(_ => {
          this.loading = false;
        });
      }
      /**
       * 开始登录时触发
       * @event login
       * @param {object} query 传递给登录接口的参数对象
       */
      this.$emit('login', query);
    }
  },
  mounted() {
    this.styleEl = this.color ? injectStyle(createStyle(this._uid, this.color)) : null;
  },
  beforeDestroy() {
    if (this.styleEl && this.styleEl.parentNode) {
      this.styleEl.parentNode.removeChild(this.styleEl);
    }
    this.styleEl = null;
  }
};
</script>
