import { defineComponent, watch, inject, toRefs, shallowRef, ref, computed, getCurrentInstance } from 'vue';
import type { SetupContext } from 'vue';
import Icon from '../../icon/src/icon';
import { AutoFocus } from '../../auto-focus';
import { inputProps, InputProps } from './input-types';
import { FORM_ITEM_TOKEN, FormItemContext } from '../../form/src/components/form-item/form-item-types';
import { useNamespace } from '@devui/shared/utils';
import { InputClearIcon } from '../../svg-icons';
import { useInputRender } from './composables/use-input-render';
import { useInputEvent } from './composables/use-input-event';
import { useInputFunction } from './composables/use-input-function';
import './input.scss';
import { createI18nTranslate } from '../../locale/create';

export default defineComponent({
  name: 'DInput',
  directives: {
    dAutoFocus: AutoFocus,
  },
  inheritAttrs: false,
  props: inputProps,
  emits: ['update:modelValue', 'focus', 'blur', 'input', 'change', 'keydown', 'clear'],
  setup(props: InputProps, ctx: SetupContext) {
    const app = getCurrentInstance();
    const t = createI18nTranslate('DInput', app);

    const formItemContext = inject(FORM_ITEM_TOKEN, undefined) as FormItemContext;
    const { modelValue, placeholder, title, autofocus } = toRefs(props);
    const ns = useNamespace('input');
    const slotNs = useNamespace('input-slot');
    const { inputDisabled, inputSize, isFocus, wrapClasses, inputClasses, customStyle, otherAttrs } = useInputRender(props, ctx);

    const input = shallowRef<HTMLInputElement>();
    const { select, focus, blur } = useInputFunction(input);

    const { onFocus, onBlur, onInput, onChange, onKeydown, onClear, onCompositionStart, onCompositionUpdate, onCompositionEnd } =
      useInputEvent(isFocus, props, ctx, focus);

    const passwordVisible = ref(false);
    const clickPasswordIcon = () => {
      passwordVisible.value = !passwordVisible.value;
      blur();
    };

    const prefixVisible = ctx.slots.prefix || props.prefix;
    const suffixVisible = ctx.slots.suffix || props.suffix || props.showPassword || props.clearable;

    const showPwdVisible = computed(() => props.showPassword && !inputDisabled.value);
    const showClearable = computed(() => {
      return props.clearable && !inputDisabled.value && modelValue.value?.length > 0;
    });

    watch(
      () => props.modelValue,
      () => {
        if (props.validateEvent) {
          formItemContext?.validate('change').catch((err) => console.warn(err));
        }
      }
    );

    ctx.expose({ select, focus, blur });

    return () => (
      <div class={inputClasses.value} {...customStyle}>
        {ctx.slots.prepend && <div class={slotNs.e('prepend')}>{ctx.slots.prepend?.()}</div>}
        <div class={wrapClasses.value}>
          {prefixVisible && (
            <span class={slotNs.e('prefix')}>
              {ctx.slots.prefix && ctx.slots.prefix?.()}
              {props.prefix && <Icon size={inputSize.value} name={props.prefix} />}
            </span>
          )}
          <input
            ref={input}
            v-dAutoFocus={autofocus.value}
            value={modelValue.value}
            disabled={inputDisabled.value}
            class={ns.e('inner')}
            placeholder={placeholder.value ?? t('placeholder')}
            {...otherAttrs}
            title={title.value}
            type={props.showPassword ? (passwordVisible.value ? 'text' : 'password') : 'text'}
            onInput={onInput}
            onFocus={onFocus}
            onBlur={onBlur}
            onChange={onChange}
            onKeydown={onKeydown}
            onCompositionstart={onCompositionStart}
            onCompositionupdate={onCompositionUpdate}
            onCompositionend={onCompositionEnd}
          />
          {suffixVisible && (
            <span class={slotNs.e('suffix')}>
              {props.suffix && <Icon size={inputSize.value} name={props.suffix} />}
              {ctx.slots.suffix && ctx.slots.suffix?.()}
              {showPwdVisible.value && (
                <Icon
                  size={inputSize.value}
                  class={ns.em('password', 'icon')}
                  name={passwordVisible.value ? 'preview' : 'preview-forbidden'}
                  onClick={clickPasswordIcon}
                />
              )}
              {showClearable.value && <InputClearIcon class={ns.em('clear', 'icon')} onClick={onClear} />}
            </span>
          )}
        </div>
        {ctx.slots.append && <div class={slotNs.e('append')}>{ctx.slots.append?.()}</div>}
      </div>
    );
  },
});