<template>
  <FlexCol>
    <view :style="{
      ...themeStyles.view.value,
      ...props.innerStyle,
    }">
      <NumberInputBox
        v-for="i of numberCount"
        :key="i"
        :index="i"
        :value="modelValue.charAt(i - 1)"
        :active="(isFocus && (i === 1)) || Boolean(modelValue.charAt(i - 1) || Boolean(modelValue.charAt(i - 2)))"
        :autoSize="autoSize"
        :isPassword="isPassword"
        :disableKeyPad="disableKeyPad"
        :showCursur="showCursur"
        :gutter="gutter"
        :boxStyle="boxStyle"
        :textStyle="textStyle"
        :borderWidth="borderWidth"
        :borderType="borderType"
        :borderColor="borderColor"
        :backgroundColor="backgroundColor"
        :activeBorderColor="activeBorderColor"
        :activeBackgroundColor="activeBackgroundColor"
        @click="onBoxClicked(i - 1)"
      />
    </view>
    <input
      v-if="useSystemInput"
      :style="themeStyles.invisibleInput.value"
      ref="inputRef"
      :value="textShadow"
      :focus="isFocus"
      :password="isPassword"
      type="number"
      @input="onInputChangeText(($event as any).detail.value)"
      @blur="onBlurInput"
    />
    <text v-if="info" :style="themeStyles.info.value">{{info}}</text>
    <text v-if="errorMessage" :style="themeStyles.errorMessage.value">{{errorMessage}}</text>

    <NumberKeyBoard
      v-model:show="showInput"
      @input="onInput"
      @delete="onDelete"
    />
  </FlexCol>
</template>

<script setup lang="ts">
import { onMounted, ref, watch } from 'vue';
import NumberKeyBoard from '../keyboard/NumberKeyBoard.vue';
import NumberInputBox from './NumberInputBox.vue';
import { propGetThemeVar, useTheme, type TextStyle, type ViewStyle } from '../theme/ThemeDefine';
import { DynamicColor, DynamicSize } from '../theme/ThemeTools';
import FlexCol from '../layout/FlexCol.vue';

/**
 * * underline 下划线
 * * box 外边框样式
 * * flat 仅有背景颜色样式
 * * activeBorderBox 外边框样式（激活状态）和背景颜色样式
 */
export type NumberInputBorderType = 'underline'|'box'|'flat'|'activeBorderBox';
export interface NumberInputProps {
  /**
   * 数值
   */
  modelValue: string;
  /**
   * 底部错误提示文案，为空时不展示
   */
  errorMessage?: string;
  /**
   * 数字位数
   * @default 6
   */
  numberCount?: number;
  /**
   * 是否是密码
   * @default false
   */
  isPassword?: boolean;
  /**
   * 是否在组件初始化时激活键盘
   * @default false
   */
  startFocus?: boolean;
  /**
   * 使用系统输入键盘，否则使用 NumberKeyBoard 作为输入键盘，默认是
   * @default true
   */
  useSystemInput?: boolean;
  /**
   * 输入框下方文字提示
   */
  info?: string;
  /**
   * 输入框格子之间的间距
   * @default 0
   */
  gutter?: number;
  /**
   * 是否自动调整宽度
   * @default false
   */
  autoSize?: boolean;
  /**
   * 格子的边框
   * @default 'activeBorderBox'
   */
  borderType?: NumberInputBorderType;
  /**
   * 格子的边框颜色
   * @default 'border.default'
   */
  borderColor?: string;
  /**
   * 格子的背景颜色
   * @default 'background.input'
   */
  backgroundColor?: string;
  /**
   * 格子的边框宽度
   * @default 1.5
   */
  borderWidth?: number;
  /**
   * 已输入格子的边框颜色
   * @default 'primary'
   */
  activeBorderColor?: string;
  /**
   * 已输入格子的背景颜色
   * @default 'background.primary'
   */
  activeBackgroundColor?: string;
  /**
   * 格子样式
   */
  boxStyle?: ViewStyle;
  /**
   * 是否禁用点击打开键盘
   * @default false
   */
  disableKeyPad?: boolean;
  /**
   * 是显示输入闪烁光标
   * @default true
   */
  showCursur?: boolean;
  /**
   * 是否在输入完成后自动收起键盘
   * @default true
   */
  finishHideKeyPad?: boolean;
  /**
   * 文字样式
   */
  textStyle?: TextStyle;
  /**
   * 外层样式
   */
  innerStyle?: ViewStyle;
}

const emit = defineEmits([ 
  /**
    * 文字更改回调
    */
  'update:modelValue', 
  /**
    * 当输入完成（全部位数都已经输入）时返回事件
    */
  'enterFinish',
]);
const props = withDefaults(defineProps<NumberInputProps>(), {
  useSystemInput: true,
  numberCount: 6,
  isPassword: false,
  autoSize: false,
  disableKeyPad: false,
  startFocus: false,
  finishHideKeyPad: true,
  showCursur: true,
  borderType: () => propGetThemeVar('NumberInputBorderType', 'activeBorderBox'),
  borderWidth: () => propGetThemeVar('NumberInputBorderWidth', 4),
  borderColor: () => propGetThemeVar('NumberInputBorderColor', 'border.default'),
  backgroundColor: () => propGetThemeVar('NumberInputBackgroundColor', 'background.input'),
  gutter: () => propGetThemeVar('NumberInputGutter', 4),
  activeBorderColor: () => propGetThemeVar('NumberInputActiveBorderColor', 'primary'),
  activeBackgroundColor: () => propGetThemeVar('NumberInputActiveBackgroundColor', 'background.primary'),
});

const themeContext = useTheme();
const themeStyles = themeContext.useThemeStyles({
  view: {
    display: 'flex',
    position: 'relative',
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
  },
  info: {
    marginTop: DynamicSize('NumberInputInfoMarginTop', 10),
    textAlign: 'center',
    color: DynamicColor('NumberInputInfoColor', 'text.second'),
  },
  errorMessage: {
    marginTop: DynamicSize('NumberInputErrorMessageMarginTop', 10),
    textAlign: 'center',
    color: DynamicColor('NumberInputErrorMessageColor', 'danger'),
  },
  invisibleInput: {
    opacity: 0,
    position: 'absolute',
    height: 1,
    left: -300,
  },
});

let lastClickBoxRet = -1;
const textShadow = ref(props.modelValue);
const inputRef = ref();
const showInput = ref(props.startFocus);
const isFocus = ref(props.startFocus);

function focusInput() {
  if (props.useSystemInput) {
    if (typeof inputRef.value?.focus === 'function')
      inputRef.value.focus();
  } else
    showInput.value = true;
  isFocus.value = true;  
}
function blurInput() {
  if (props.useSystemInput) {
    if (typeof inputRef.value?.blur === 'function')
      inputRef.value.blur();
  } else
    showInput.value = false;
  isFocus.value = false;
}
function onBlurInput() {
  isFocus.value = false;
}

function onInputChangeText(text: string) {
  //点击了前面的方格输入，需要清除方格后面的文字
  if (lastClickBoxRet >= 0 && text.length > lastClickBoxRet) {
    text = (text.substring(0, lastClickBoxRet) + text.charAt(text.length - 1));
    lastClickBoxRet = -1;
  }
  if (text.length > props.numberCount)
    return;

  textShadow.value = text;
  if (text.length === props.numberCount) {
    emit('enterFinish', text);
    if (props.finishHideKeyPad)
      blurInput();
  }
}
function onBoxClicked(i: number) {
  lastClickBoxRet = i;
  focusInput();
}
function onInput(str: string) {
  onInputChangeText(textShadow.value + str);
}
function onDelete() {
  onInputChangeText(textShadow.value.substring(0, textShadow.value.length - 1));
}

watch(textShadow, (val) => {
  emit('update:modelValue', val);
});
onMounted(() => {
  if (props.startFocus)
    focusInput();
});

</script>