import type { PropType } from 'vue';
import { defineComponent, shallowRef } from 'vue';
import PropTypes from './vue-types';

export interface BaseInputInnerExpose {
  focus: () => void;
  blur: () => void;
  input: HTMLInputElement | HTMLTextAreaElement | null;
  setSelectionRange: (
    start: number,
    end: number,
    direction?: 'forward' | 'backward' | 'none',
  ) => void;
  select: () => void;
  getSelectionStart: () => number | null;
  getSelectionEnd: () => number | null;
  getScrollTop: () => number | null;
  setScrollTop: (scrollTop: number) => void;
}
const BaseInputInner = defineComponent({
  // inheritAttrs: false,
  props: {
    disabled: PropTypes.looseBool,
    type: PropTypes.string,
    value: PropTypes.any,
    tag: {
      type: String as PropType<'input' | 'textarea'>,
      default: 'input',
    },
    size: PropTypes.string,
    onChange: Function as PropType<(e: Event) => void>,
    onInput: Function as PropType<(e: Event) => void>,
    onBlur: Function as PropType<(e: Event) => void>,
    onFocus: Function as PropType<(e: Event) => void>,
    onKeydown: Function as PropType<(e: Event) => void>,
    onCompositionstart: Function as PropType<(e: Event) => void>,
    onCompositionend: Function as PropType<(e: Event) => void>,
    onKeyup: Function as PropType<(e: Event) => void>,
    onPaste: Function as PropType<(e: Event) => void>,
    onMousedown: Function as PropType<(e: Event) => void>,
  },
  emits: [
    'change',
    'input',
    'blur',
    'keydown',
    'focus',
    'compositionstart',
    'compositionend',
    'keyup',
    'paste',
    'mousedown',
  ],
  setup(props, { expose }) {
    const inputRef = shallowRef(null);

    const focus = () => {
      if (inputRef.value) {
        inputRef.value.focus();
      }
    };
    const blur = () => {
      if (inputRef.value) {
        inputRef.value.blur();
      }
    };
    const setSelectionRange = (
      start: number,
      end: number,
      direction?: 'forward' | 'backward' | 'none',
    ) => {
      inputRef.value?.setSelectionRange(start, end, direction);
    };

    const select = () => {
      inputRef.value?.select();
    };
    expose({
      focus,
      blur,
      input: inputRef,
      setSelectionRange,
      select,
      getSelectionStart: () => inputRef.value?.selectionStart,
      getSelectionEnd: () => inputRef.value?.selectionEnd,
      getScrollTop: () => inputRef.value?.scrollTop,
    });
    return () => {
      const { tag: Tag, value, ...restProps } = props;
      return <Tag {...restProps} ref={inputRef} value={value} />;
    };
  },
});

export default BaseInputInner;
