<template>
  <Touchable
    :touchable="touchable || childOnClickListener !== undefined"
    :pressedColor="themeContext.resolveThemeColor('FieldPressedColor', 'pressed.white')"
    :innerStyle="{ 
      ...themeStyles.field.value, 
      ...(showBottomBorder ? themeStyles.fieldBorder.value : {}),
      ...(labelPosition === 'top' ? themeStyles.fieldVertical.value : {}), 
      ...fieldStyle, 
      ...(focused ? activeFieldStyle : {}),
      ...(error || finalErrorMessage ? errorFieldStyle : {})
    }"
    :setCursor="false"
    :direction="labelPosition === 'top' ? 'column' : 'row'"
    :justify="labelPosition === 'top' ? 'flex-start' : 'center'"
    @click="onClick"
  >
    <!-- 左边的标签区域 -->
    <FlexRow 
      v-if="showLabel !== false && label" 
      align="center" 
      :flex="labelFlex"
      :innerStyle="{
        width: themeContext.resolveThemeSize(labelWidth),
      }"
      :justify="selectStyleType(labelAlign, 'left', {
        left: 'flex-start',
        center: 'center',
        right: 'flex-end',
      })"
    >
      <text v-if="requiredShow && showRequiredBadge" :style="themeStyles.requiredMark.value">*</text>
      <slot name="leftIcon" />
      <view v-if="!label" :style="labelStyle" />
      <text v-else :style="{
        ...themeStyles.labelText.value,
        ...labelStyle,
        color: themeContext.resolveThemeColor(disabled ? labelDisableColor : labelColor),
      }">
        {{ label + (colon ? ': ' : '') }}
      </text>
    </FlexRow>

    <!-- 输入框区域 -->
    <FlexCol :flex="inputFlex">
      <FlexRow 
        justify="space-between"
        align="center" 
        :innerStyle="themeStyles.inputWapper2.value"
      >
        <slot name="prefix" />
        <slot name="leftButton" />
        <slot name="control" />
        <slot>
          <FlexRow v-if="tags" wrap align="center" :gap="10">
            <Tag 
              v-for="(tag, index) in tagSplited"
              :key="index"
              :text="tag"
              color="primary"
              size="small"
              closeable
              @close="onTagDelete(tag)"
            />
            <input 
              ref="inputRef"
              :style="{
                ...themeStyles.input.value,
                ...inputStyle,
                ...(focused ? activeInputStyle : {}),
                color: themeContext.resolveThemeColor(disabled ? inputDisableColor : (error ? errorTextColor : inputColor)),
              }"
              :value="tagInputString"
              :placeholder="placeholder"
              :placeholder-style="`color: ${themeContext.resolveThemeColor(error ? errorTextColor : placeholderTextColor)}`"
              confirm-type="done"
              type="text"
              :maxlength="200"
              :disabled="disabled"
              :readonly="readonly"
              @focus="onFocus"
              @blur="onBlur"
              @input="onTagInputInput"
              @confirm="onTagInputConfirm"
            />
          </FlexRow>
          <textarea 
            v-else-if="multiline"
            ref="inputRef"
            :style="{
              ...themeStyles.input.value,
              ...inputStyle,
              ...(focused ? activeInputStyle : {}),
              color: themeContext.resolveThemeColor(disabled ? inputDisableColor : (error ? errorTextColor : inputColor)),
              textAlign: inputAlign,
            }"
            :autoHeight="autoHeight"
            :value="inputValue"
            :password="type==='password'"
            :placeholder="placeholder"
            :placeholder-style="`color: ${themeContext.resolveThemeColor(error ? errorTextColor : placeholderTextColor)}`"
            :confirm-type="confirmType"
            :rows="rows"
            :maxlength="maxLength"
            :disabled="disabled || readonly"
            @input="onInput"
            @focus="onFocus"
            @blur="onBlur"
            @confirm="onBlur"
            @click="onClick"
          />
          <input 
            v-else
            ref="inputRef"
            :style="{
              ...themeStyles.input.value,
              ...inputStyle,
              ...(focused ? activeInputStyle : {}),
              color: themeContext.resolveThemeColor(disabled ? inputDisableColor : (error ? errorTextColor : inputColor)),
              textAlign: inputAlign,
            }"
            :value="inputValue"
            :password="type==='password'"
            :placeholder="placeholder"
            :placeholder-style="`color: ${themeContext.resolveThemeColor(error ? errorTextColor : placeholderTextColor)}`"
            :confirm-type="confirmType"
            :type="selectStyleType(type, 'text', {
              text: 'text',
              password: 'text',
              number: 'number',
              decimal: 'digit',
              tel: 'tel',
              email: 'text',
              nickname: 'nickname',
            }) || 'text'"
            :maxlength="maxLength"
            :disabled="disabled || readonly"
            @input="onInput"
            @focus="onFocus"
            @blur="onBlur"
            @confirm="onBlur"
            @click="onClick"
          />
        </slot>
        <slot name="suffix" />
        <slot name="rightButton" />
        <Icon v-if="showRightArrow" icon="arrow-right" :size="themeContext.resolveThemeSize('FieldRightArrowSize', 30)" v-bind="rightArrowProps" />
      </FlexRow>
      <!-- 错误提示图标和文本 -->
      <FlexRow 
        v-if="finalErrorMessage"
        :gap="10"
        :innerStyle="themeStyles.errorMessage.value"
        align="center"
      >
        <Icon 
          :icon="errorIcon"
          :size="themeContext.resolveThemeSize('FieldErrorIconSize', 40)" 
          v-bind="errorIconProps" 
          :color="themeContext.resolveThemeColor('FieldErrorMessageColor', 'danger')"
        />
        <text :style="themeStyles.errorMessageText.value">{{finalErrorMessage}}</text>
      </FlexRow>
      <!-- 额外的提示信息 -->
      <FlexRow 
        v-if="extraMessage && !readonly"
        :gap="10"
        :innerStyle="themeStyles.extraMessage.value"
        align="center"
      >
        <Icon 
          :icon="extraIcon"
          :size="themeContext.resolveThemeSize('FieldExtraIconSize', 40)" 
          v-bind="extraIconProps" 
          :color="themeContext.resolveThemeColor('FieldExtraIconColor', 'text.second')"
        />
        <text :style="themeStyles.extraMessageText.value">{{extraMessage}}</text>
      </FlexRow>
      <text v-if="showWordLimit" :style="themeStyles.wordLimitText.value">{{wordLimitText}}</text>

    </FlexCol>
    <!-- 清除按钮 -->
    <IconButton
      v-if="(clearButton && (
        clearButtonMode === 'always'
        || (clearButtonMode === 'while-editing' && focused))
        || (clearButtonMode === 'unless-editing' && modelValue !== '')
      )"
      icon="delete-filling" 
      :color="themeContext.resolveThemeColor('FieldClearIconColor', 'grey')"
      v-bind="clearButtonProps"
      @click="onClear"
    />
  </Touchable>
  <slot name="extra" />
</template>

<script setup lang="ts">
import { computed, inject, onBeforeUnmount, onMounted, provide, ref, toRef, watch } from 'vue';
import { propGetThemeVar, useTheme, type TextStyle, type ViewStyle } from '../theme/ThemeDefine';
import { FormItemContextContextKey, propGetFormContext, type FormContext, type FormItemContext, type FormItemInternalContext } from './FormContext';
import { DynamicColor, DynamicSize, DynamicVar, selectStyleType } from '../theme/ThemeTools';
import type { IconProps } from '../basic/Icon.vue';
import Icon from '../basic/Icon.vue';
import IconButton from '../basic/IconButton.vue';
import FlexCol from '../layout/FlexCol.vue';
import FlexRow from '../layout/FlexRow.vue';
import Touchable from '../feedback/Touchable.vue';
import type { TextProps } from '../basic/Text.vue';
import type { RuleItem } from 'async-validator';
import Tag from '../display/Tag.vue';


export interface FieldInstance {
  /**
   * 获取输入框焦点
   */
  focus: () => void;
  /**
   * 取消输入框焦点
   */
  blur: () => void;
  /**
   * 清空输入框
   */
  clear: () => void;
  /**
   * 返回值表明当前输入框是否获得了焦点。
   */
  isFocused: () => boolean;
  /**
   * 清除当前条目的校验状态
   */
  clearValidate: () => void;
}
export interface FieldProps {
  modelValue?: any,
  /**
   * 输入框左侧文本
   */
  label?: string;
  /**
   * 名称，作为提交表单时的标识符
   */
  name?: string;
  /**
   * 是否可点击.可以作为一个纯点击条目
   */
  touchable?: boolean;
  /**
   * 输入框类型
   * @default 'text'
   */
  type?: 'text'|'tel'|'number'|'password'|'number'|'email'|'decimal'|'nickname';
  /**
   * 输入的最大字符数
   */
  maxLength?: number;
  /**
   * 输入框占位提示文字
   */
  placeholder?: string;
  /**
   * 是否禁用输入框
   * @default false
   */
  disabled?: boolean;
  /**
   * 是否只读
   * @default false
   */
  readonly?: boolean;
  /**
   * 是否内容垂直居中
   * @default false
   */
  center?: boolean;
  /**
   * 是否在 label 后面添加冒号
   * @default true
   */
  colon?: boolean;
  /**
   * 是否必填
   * @default false
   */
  required?: boolean;
  /**
   * 多行文字
   * @default false
   */
  multiline?: boolean;
  /**
   * 多行文字的行数
   * @default undefined
   */
  rows?: number|string;
  /**
   * 多行文字下是否自动调整高度
   * @default false
   */
  autoHeight?: boolean;
  /**
   * 是否显示表单必填星号
   * @default true
   */
  showRequiredBadge?: boolean;
  /**
   * 是否启用清除图标，点击清除图标后会清空输入框
   * @default false
   */
  clearButton?: boolean;
  /**
   * 清除图标的自定义属性
   */
  clearButtonProps?: IconProps;
  /**
   * 清除图标的显示模式
   */
  clearButtonMode?: 'always'|'while-editing'|'unless-editing';
  /**
   * 左侧文本的宽度
   */
  labelWidth?: string|number|undefined;
  /**
   * 左侧文本对齐
   * @default 'left'
   */
  labelAlign?: 'left'|'center'|'right';
  /**
   * 左侧文本的位置
   * @default 'left'
   */
  labelPosition?: 'top'|'left';
  /**
   * 左侧文本的flex占比
   * @default undefined
   */
  labelFlex?: number;
  /**
   * 输入框的flex占比
   * @default 5
   */
  inputFlex?: number;
  /**
   * 左侧文本的样式
   */
  labelStyle?: TextStyle;
  /**
   * 左侧文本的颜色
   */
  labelColor?: string;
  /**
   * 左侧文本的禁用颜色
   */
  labelDisableColor?: string;
  /**
   * 输入框样式
   */
  inputStyle?: TextStyle;
  /**
   * 激活时的外壳样式
   */
  activeInputStyle?: TextStyle;
  /**
   * 输入框颜色
   */
  inputColor?: string;
  /**
   * 输入框文本对齐。
   * @default 'left'
   */
  inputAlign?: 'left'|'center'|'right';
  /**
   * 输入框禁用颜色
   */
  inputDisableColor?: string;
  /**
   * 外壳样式
   */
  fieldStyle?: ViewStyle;
  /**
   * 激活时的外壳样式
   */
  activeFieldStyle?: ViewStyle;
  /**
   * 错误时的外壳样式
   */
  errorFieldStyle?: ViewStyle;
  /**
   * 错误时的文字颜色
   * @default danger
   */
  errorTextColor?: string;

  /**
   * 额外的提示信息
   */
  extraMessage?: string;
  extraMessageProps?: TextProps;
  /**
   * 额外的提示图标
   * @default 'prompt'
   */
  extraIcon?: string;
  extraIconProps?: IconProps;
  /**
   * send	右下角按钮为“发送”
      search	右下角按钮为“搜索”
      next	右下角按钮为“下一个”
      go	右下角按钮为“前往”
      done	右下角按钮为“完成”
      return	右下角按钮为“换行”
   */
  confirmType?: 'send'|'search'|'next'|'go'|'done'|'return';
  /**
   * 文本框水印文字颜色
   * @default Color.grey
   */
  placeholderTextColor?: string;
  /**
   * 输入内容格式化函数
   */
  formatter?: (text: string) => string;
  /**
   * 格式化函数触发的时机，可选值为 blur
   * @default 'input'
   */
  formatTrigger?: 'blur'|'input';
  /**
   * 设置字段校验的时机
   * * blur 文本框失去焦点时校验
   * * change 数值更改时校验
   * * submit 提交时校验(默认)
   * @default 'submit'
   */
  validateTrigger?: 'blur'|'change'|'submit';
  /**
   * 是否将输入内容标红。
   */
  error?: boolean;
  /**
   * 错误提示的图标
   * @default 'prompt'
   */
  errorIcon?: string;
  /**
   * 错误提示图标的自定义属性
   */
  errorIconProps?: IconProps;
  /**
   * 底部错误提示文案，为空时不展示
   */
  errorMessage?: string;
  /**
   * 点击输入框是否重置错误状态
   * @default true
   */
  resetErrorOnClick?: boolean;
  /**
   * 是否显示字数统计
   * @default false
   */
  showWordLimit?: boolean;
  /**
   * 是否显左边标题
   * @default true
   */
  showLabel?: boolean;
  /**
   * 是否显右边箭头
   * @default false
   */
  showRightArrow?: boolean;
  /**
   * 是否显示底部边框
   * @default true
   */
  showBottomBorder?: boolean;
  /**
   * 右边箭头的自定义属性
   */
  rightArrowProps?: IconProps;
  /**
   * 当前条目的校验规则
   */
  rules?: RuleItem[],

  /**
   * 是否显示输入标签模式
   * @default false
   */
  tags?: boolean,
  /**
   * 输入标签模式下，标签之间的连接符
   * @default ','
   */
  tagJoinType?: string,

  requireChildRef?: () => any,
}

defineOptions({
  options: {
    styleIsolation: "shared",
    virtualHost: true,
  }
})

const emit = defineEmits([ 'update:modelValue', 'click', 'blur', 'focus', 'clear' ])

const props = withDefaults(defineProps<FieldProps>(), {
  label: '',
  labelColor: () => propGetThemeVar('FieldLabelColor', propGetFormContext()?.fieldProps.value?.labelColor ?? 'text.content'),
  labelDisableColor: () => propGetThemeVar('FieldLabelDisableColor', propGetFormContext()?.fieldProps.value?.labelDisableColor ?? 'grey'),
  labelFlex: () => propGetThemeVar('FieldLabelFlex', propGetFormContext()?.labelFlex.value)!,
  inputDisableColor: () => propGetThemeVar('FieldInputDisableColor', propGetFormContext()?.fieldProps.value?.inputDisableColor ?? 'grey'),
  inputColor: () => propGetThemeVar('FieldInputColor', propGetFormContext()?.fieldProps.value?.inputColor ?? 'text.content'),
  inputFlex: () => propGetThemeVar('FieldInputFlex', propGetFormContext()?.inputFlex.value ?? 5),
  placeholderTextColor: () => propGetThemeVar('FieldPlaceholderTextColor', propGetFormContext()?.fieldProps.value?.placeholderTextColor ?? 'text.second'),
  errorTextColor: () => propGetThemeVar('FieldErrorTextColor', propGetFormContext()?.fieldProps.value?.errorTextColor ?? 'danger'),
  resetErrorOnClick: () => propGetThemeVar('FieldResetErrorOnClick', propGetFormContext()?.fieldProps.value?.resetErrorOnClick ?? true),
  colon: () => propGetFormContext()?.colon.value ?? true,
  fieldStyle: () =>  propGetFormContext()?.fieldProps.value?.fieldStyle ?? propGetThemeVar('FieldFieldStyle', {}),
  activeFieldStyle: () => propGetFormContext()?.fieldProps.value?.activeFieldStyle ?? propGetThemeVar('FieldActiveFieldStyle', {}),
  errorFieldStyle: () => propGetFormContext()?.fieldProps.value?.errorFieldStyle ?? propGetThemeVar('FieldErrorFieldStyle', {}),
  labelStyle: () => propGetThemeVar('FieldLabelStyle', propGetFormContext()?.fieldProps.value?.labelStyle ?? {}),
  inputStyle: () => propGetThemeVar('FieldInputStyle', propGetFormContext()?.fieldProps.value?.inputStyle ?? {}),
  activeInputStyle: () => propGetThemeVar('FieldActiveInputStyle', propGetFormContext()?.fieldProps.value?.activeInputStyle ?? {}),
  required: false,
  showBottomBorder: () => propGetFormContext()?.fieldProps.value?.showBottomBorder ?? true,
  center: () => propGetFormContext()?.fieldProps.value?.center ?? true,
  showWordLimit: () => propGetFormContext()?.fieldProps.value?.showWordLimit ?? false,
  clearButton: () => propGetFormContext()?.fieldProps.value?.clearButton ?? false,
  clearButtonMode: () => propGetFormContext()?.fieldProps.value?.clearButtonMode ?? 'always',
  labelWidth: () => propGetFormContext()?.labelWidth.value!,
  labelAlign: () => propGetFormContext()?.labelAlign.value ?? "left",
  labelPosition: () => propGetFormContext()?.labelPosition.value ?? 'left',
  inputAlign: () => propGetFormContext()?.fieldProps.value?.inputAlign ?? "left",
  type: () => propGetFormContext()?.fieldProps.value?.type ?? "text",
  formatTrigger: () => propGetFormContext()?.fieldProps.value?.formatTrigger ?? 'input',
  showLabel: () => propGetFormContext()?.showLabel.value ?? true,
  showRequiredBadge: () => propGetFormContext()?.fieldProps.value?.showRequiredBadge ?? true,
  showRightArrow: () => propGetFormContext()?.fieldProps.value?.showRightArrow ?? false,
  disabled: false,
  readonly: false,
  autoHeight: false,
  maxLength: 100,
  modelValue: undefined,
  tags: false,
  tagJoinType: ',',
  errorIcon: () => propGetThemeVar('FieldErrorIcon', 'prompt'),
  errorIconProps: () => propGetThemeVar('FieldErrorIconProps', propGetFormContext()?.fieldProps.value?.errorIconProps ?? {}),
  extraMessage: '',
  extraMessageProps: () => propGetThemeVar('FieldExtraMessageProps', propGetFormContext()?.fieldProps.value?.extraMessageProps ?? {}),
  extraIcon: () => propGetThemeVar('FieldExtraIcon', 'prompt'),
  extraIconProps: () => propGetThemeVar('FieldExtraIconProps', propGetFormContext()?.fieldProps.value?.extraIconProps ?? {}),
});

//#region Context

const formContextProps = inject<FormContext>('formContext', null as any);
const error = ref<string|null>(null);
const finalErrorMessage = computed(() => {
  return props.errorMessage || error.value || '';
})
const errorState = computed(() => Boolean(finalErrorMessage.value));
const childOnClickListener = ref<(() => void)|undefined>(undefined);

//Context for parent
const formItemInternalContext : FormItemInternalContext = {
  getExpectedRef: () => {
    return props.requireChildRef?.() ?? fieldInstance;
  },
  getItemRules: () => props.rules ?? [],
  getValidateTrigger: () => props.validateTrigger || formContextProps?.validateTrigger.value || 'submit',
  getFieldName: () => props.name ?? '',
  setErrorState(errorMessage) { error.value = errorMessage; },
  getUniqueId() {
    return uniqueId;
  },
  setBlurState() {
    inputRef.value?.blur();
  },
};
//Context for custom children
const formItemContext : FormItemContext = {
  errorState: errorState,
  getFieldName: () => {
    return props.name ?? uniqueId;
  },
  onFieldFocus: () => {
    formContextProps?.onFieldFocus(formItemInternalContext); 
    emit('focus');
  },
  onFieldBlur: () => { 
    formContextProps?.onFieldBlur(formItemInternalContext); 
    emit('blur');
  },
  getFormModelValue: () => formContextProps?.getItemValue(formItemInternalContext),
  onFieldChange: (newValue: unknown) => { formContextProps?.onFieldChange(formItemInternalContext, newValue); },
  clearValidate: () => { formContextProps?.clearValidate(formItemInternalContext); },
  setOnClickListener(listener: (() => void)|undefined) {
    childOnClickListener.value = listener;
  },
  disabled: toRef(props, 'disabled'),
  readonly: toRef(props, 'readonly'),
}
provide(FormItemContextContextKey, formItemContext);

//Add ref in form
const addNumber = formContextProps?.addFormItemField(formItemInternalContext);
const uniqueId = (formContextProps?.name || 'form') + 'Item' + (props.name || `unknowProperity${addNumber}`);

onBeforeUnmount(() => {
  formContextProps?.removeFormItemField(formItemInternalContext);
})

//#endregion

const themeContext = useTheme();

const themeStyles = themeContext.useThemeStyles({
  field: {
    backgroundColor: DynamicColor('FieldBackgroundColor', 'background.cell'),
    paddingVertical: DynamicSize('FieldPaddingVertical', 16),
    paddingHorizontal: DynamicSize('FieldPaddingHorizontal', 20),
  },
  fieldBorder: {
    borderBottomWidth: DynamicSize('FieldBorderBottomWidth', '1px'),
    borderBottomColor: DynamicColor('FieldBorderBottomColor', 'border.cell'),
    borderBottomStyle: 'solid',
  },
  fieldVertical: {
    gap: DynamicSize('FieldVerticalGap', 20),
  },
  requiredMark: {
    fontSize: DynamicSize('FieldRequiredMark', 28),
    alignSelf: 'flex-start',
    color: DynamicColor('FieldRequiredMark', 'danger'),
    paddingVertical: DynamicSize('FieldRequiredMarkPaddingVertical', 8),
    marginHorizontal: DynamicSize('FieldRequiredMarkMarginHorizontal', 8),
  },
  labelText: {
    marginRight: DynamicSize('FieldLabelMarginRight', 20),
    fontSize: DynamicSize('FieldLabelFontSize', 28),
    alignSelf: 'flex-start',
    paddingVertical: DynamicSize('FieldLabelPaddingVertical', 8),
  },
  inputWapper2: {
    align: 'center',
    alignSelf: 'center',
    width: '100%',
  },
  input: {
    flex: 1,
    width: 'auto',
    minWidth: '100rpx',
    paddingVertical: DynamicSize('FieldInputPaddingVertical', 0),
    paddingHorizontal: DynamicSize('FieldInputPaddingHorizontal', 0),
  },
  errorMessageText: {
    fontSize: DynamicSize('FieldErrorMessageFontSize', 24),
    color: DynamicColor('FieldErrorMessageColor', 'danger'),
  },
  errorMessage: {
    marginTop: DynamicSize('FieldErrorMessageMarginTop', 12),
  },
  extraMessageText: {
    fontSize: DynamicSize('FieldExtraMessageFontSize', 24),
    color: DynamicColor('FieldExtraMessageColor', 'text.second'),
  },
  extraMessage: {
    marginTop: DynamicSize('FieldExtraMessageMarginTop', 12),
  },
  wordLimitText: {
    fontSize: DynamicSize('FieldWordLimitTextFontSize', 24),
    color: DynamicColor('FieldWordLimitTextColor', 'text.second'),
    width: DynamicSize('FieldWordLimitTextWidth', '100%'),
    textAlign: DynamicVar('FieldWordLimitTextTextAlign', 'right'),
  },
  clearIcon: {
    width: DynamicSize('FieldClearIconWidth', 60),
    justifyContent: 'center',
    alignItems: 'center',
  },
});
const readonly = computed(() => {
  return props.readonly || formContextProps?.readonly.value || false;
});
const disabled = computed(() => {
  return props.disabled || formContextProps?.disabled.value || false;
});

const requiredShow = computed(() => {
  return props.required == true || formContextProps?.getItemRequieed(formItemInternalContext);
});
const wordLimitText = computed(() => {
  let wordString = props.modelValue ? props.modelValue.length : '0';
  if (props.maxLength)
    wordString += `/${props.maxLength}`;
  else
    wordString += `字`;
  return wordString
});
const inputValue = ref();
const focused = ref(false);
const inputRef = ref();

watch(() => props.modelValue, (newValue) => {
  inputValue.value = newValue;
});
onMounted(() => {
  inputValue.value = props.modelValue ?? formItemContext.getFormModelValue();
});

function emitChangeText(text: string) {
  emit('update:modelValue', text);
  inputValue.value = text;
  formItemContext.onFieldChange(text);
}
function doFormatter(text: string) {
  switch (props.type) {
    case 'decimal':
      text = text.replace(/[^\d.]/g, "");
      text = text.replace(/^\./g, ""); //必须保证第一个为数字而不是.
      text = text.replace(/\.{2,}/g, "."); //保证只有出现一个.而没有多个.
      text = text.replace(".","$#$").replace(/\./g, "").replace("$#$", ".");
      break;
    case 'number':
      text = text.replace(/[^\d]/g, '');
      break;
    case 'tel':
      text = text.replace(/[^(\d|\-|*|#)]/g, '');
      break;
  }
  if (props.formatter)
    text = props.formatter(text);
  return text;
}
function onInput(e: any) {
  focused.value = true;
  let text = e.detail.value;
  if (props.formatTrigger !== 'blur') //格式化字符串
    text = doFormatter(text);
  emitChangeText(text);
}
function onFocus() {
  focused.value = true;
  formItemContext.onFieldFocus();
}
function onBlur() {
  focused.value = false;
   if (props.formatTrigger === 'blur'){//格式化字符串
    const text = doFormatter(props.modelValue ?? '');
    emitChangeText(text);
  }
  formItemContext.onFieldBlur();
}
function onClear() {
  //清空按钮
  emitChangeText('');
  emit('clear'); 
}
function onClick() {
  if (props.resetErrorOnClick)
    fieldInstance.clearValidate();
  if (props.disabled || props.readonly)
    return;
  childOnClickListener.value?.();
  emit('click');
}

//#region 标签输入框事件处理

const tagInputString = ref('');
const tagSplited = computed<string[]>(() => {
  let str = props.modelValue;
  if (typeof str === 'string')
    return (props.modelValue  as string|| '').split(props.tagJoinType).filter(x => x);
  return [];
});

function onTagDelete(tag: string) {
  const tags = tagSplited.value.concat();
  const index = tags.indexOf(tag);
  if (index !== -1) {
    tags.splice(index, 1);
    emitChangeText(tags.join(props.tagJoinType));
  }
}
function onTagInputInput(e: any) {
  focused.value = true;
  tagInputString.value = e.detail.value;
}
function onTagInputConfirm() {
  if (tagInputString.value && !tagSplited.value.includes(tagInputString.value)) {
    emitChangeText(props.modelValue + props.tagJoinType + tagInputString.value);
    tagInputString.value = '';
  }
}

//#endregion 

const fieldInstance : FieldInstance = {
  focus() {
    inputRef.value?.focus();
  },
  blur() {
    inputRef.value?.blur();
  },
  clear() {
    inputRef.value?.clear();
  },
  isFocused() :boolean {
    return focused.value;
  },
  clearValidate() {
    formContextProps?.clearValidate(formItemInternalContext);
  }
}

defineExpose<FieldInstance>(fieldInstance);
</script>