<template>
  <div>
    <div class="kole-code" @paste="onPaste">
      <div
        v-for="(c, i) in cells"
        :key="i"
        class="kole-code-cell"
        :class="{ 'is-focus': focusedIndex === i, 'is-filled': !!cells[i], 'is-masked': masked }"
      >
        <input
          ref="inputs"
          class="kole-code-input"
          :value="cells[i]"
          maxlength="1"
          inputmode="numeric"
          :aria-label="'验证码第 ' + (i + 1) + ' 位'"
          @focus="focusedIndex = i"
          @input="onInput($event, i)"
          @keydown="onKeydown($event, i)"
        />
      </div>
    </div>
    <div class="kole-code-tip" :class="{ error: hasError }">{{ tip }}</div>
  </div>
</template>

<script setup>
import { ref, watch } from 'vue';

const props = defineProps({
  modelValue: { type: String, default: '' },
  length: { type: Number, default: 6 },
  masked: { type: Boolean, default: false },
  tip: { type: String, default: '' },
  hasError: { type: Boolean, default: false }
});
const emit = defineEmits(['update:modelValue', 'change']);

const inputs = ref([]);
const focusedIndex = ref(-1);

function buildCells(v) {
  const arr = (v || '').split('').slice(0, props.length);
  while (arr.length < props.length) arr.push('');
  return arr;
}
const cells = ref(buildCells(props.modelValue));

watch(
  () => props.modelValue,
  (v) => { cells.value = buildCells(v); }
);
watch(
  () => props.length,
  () => { cells.value = buildCells(cells.value.join('')); }
);

function emitChange() {
  const code = cells.value.join('');
  emit('update:modelValue', code);
  emit('change', code);
}
function focus(i) {
  inputs.value[i] && inputs.value[i].focus();
}
function onInput(e, i) {
  const ch = (e.target.value || '').slice(-1);
  cells.value[i] = ch;
  e.target.value = ch;
  if (ch && i < props.length - 1) focus(i + 1);
  emitChange();
}
function onKeydown(e, i) {
  if (e.key === 'Backspace') {
    e.preventDefault();
    if (cells.value[i]) {
      cells.value[i] = '';
    } else if (i > 0) {
      cells.value[i - 1] = '';
      focus(i - 1);
    }
    emitChange();
  } else if (e.key === 'ArrowLeft' && i > 0) {
    focus(i - 1);
  } else if (e.key === 'ArrowRight' && i < props.length - 1) {
    focus(i + 1);
  }
}
function onPaste(e) {
  e.preventDefault();
  const text = (e.clipboardData || window.clipboardData).getData('text') || '';
  const digits = text.replace(/\D/g, '').slice(0, props.length).split('');
  const arr = cells.value.slice();
  for (let k = 0; k < props.length; k++) arr[k] = digits[k] || '';
  cells.value = arr;
  focus(Math.min(digits.length, props.length - 1));
  emitChange();
}
</script>

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