<template>
  <div class="kole-card">
    <div class="kole-card-field" :class="{ 'is-focus': focused, 'is-valid': valid, 'is-invalid': invalid }">
      <input
        class="kole-card-input"
        :value="display"
        inputmode="numeric"
        maxlength="23"
        :placeholder="placeholder"
        @input="onInput"
        @focus="focused = true"
        @blur="focused = false"
      />
      <span class="kole-card-type" :class="{ unknown: !cardType }">{{ cardType || '未知' }}</span>
    </div>
    <div class="kole-card-tip" :class="tipClass">{{ tipText }}</div>
  </div>
</template>

<script>
export default {
  name: 'KoleBankCardInput',
  props: {
    value: { type: String, default: '' },
    placeholder: { type: String, default: '请输入银行卡号' }
  },
  data() {
    return { digits: this.value.replace(/\D/g, ''), focused: false };
  },
  computed: {
    display() {
      return this.digits.replace(/(.{4})/g, '$1 ').trim();
    },
    cardType() {
      var v = this.digits;
      if (/^4/.test(v)) return 'Visa';
      if (/^5[1-5]/.test(v)) return 'MasterCard';
      if (/^62/.test(v)) return '银联';
      if (/^3[47]/.test(v)) return 'AmEx';
      if (/^35/.test(v)) return 'JCB';
      return '';
    },
    luhn() {
      var v = this.digits, sum = 0, alt = false;
      for (var i = v.length - 1; i >= 0; i--) {
        var n = parseInt(v[i], 10);
        if (alt) { n *= 2; if (n > 9) n -= 9; }
        sum += n; alt = !alt;
      }
      return sum % 10 === 0;
    },
    valid() {
      return this.digits.length >= 13 && this.luhn;
    },
    invalid() {
      return this.digits.length >= 13 && !this.luhn;
    },
    tipClass() {
      return this.valid ? 'valid' : this.invalid ? 'invalid' : '';
    },
    tipText() {
      if (this.digits.length === 0) return '支持 Visa / MasterCard / 银联等';
      if (this.valid) return '卡号校验通过';
      if (this.invalid) return '卡号未通过 Luhn 校验';
      return '继续输入卡号…';
    }
  },
  methods: {
    onInput(e) {
      this.digits = e.target.value.replace(/\D/g, '').slice(0, 19);
      e.target.value = this.display;
      this.$emit('input', this.digits);
    }
  }
};
</script>

<style src="./BankCardInput.css"></style>
