import { computed, defineComponent, ref, watch } from 'vue';
import { debounce } from 'lodash-es';
import {
  getEditorEmits,
  getInputProps,
  useNamespace,
} from '@ibiz-template/vue-util';
import '@ibiz-template/theme/style/components/editor/ibiz-input/ibiz-input.scss';

export const IBizInput = defineComponent({
  name: 'IBizInput',
  props: getInputProps(),
  emits: getEditorEmits(),
  setup(props, { emit }) {
    const ns = useNamespace('input');
    const c = props.controller;
    const editorModel = c.model;
    const inputRef = ref();
    let autoSize: boolean | { minRows: Number; maxRows?: Number } = {
      minRows: 2,
    };

    // 文本域默认行数，仅在 textarea 类型下有效
    const rows = ref(2);
    if (editorModel.editorType === 'TEXTAREA_10') {
      rows.value = 10;
      autoSize = {
        minRows: 10,
      };
    }

    // 类型
    const type = computed(() => {
      switch (editorModel.editorType) {
        case 'TEXTBOX':
          return 'text';
        case 'PASSWORD':
          return 'password';
        case 'TEXTAREA':
        case 'TEXTAREA_10':
          return 'textarea';
        default:
          return 'string';
      }
    });

    if (editorModel.editorParams) {
      if (editorModel.editorParams.autosize) {
        try {
          autoSize = JSON.parse(editorModel.editorParams.autosize);
        } catch {
          autoSize = false;
        }
      }
    }
    const currentVal = ref<string>('');

    watch(
      () => props.value,
      (newVal, oldVal) => {
        if (newVal !== oldVal) {
          if (!newVal) {
            currentVal.value = '';
          } else {
            currentVal.value = newVal;
          }
        }
      },
      { immediate: true },
    );

    let isDebounce = false;
    let awaitSearch: () => void;
    let blurCacheValue: string | undefined;
    // 防抖值变更回调
    const debounceChange = debounce(
      (e: IData) => {
        // 拦截掉blur触发后change
        if (blurCacheValue !== e.target.value) {
          emit('change', e.target.value);
        }
        blurCacheValue = undefined;
        isDebounce = false;
        if (awaitSearch) {
          awaitSearch();
        }
      },
      300,
      { leading: true },
    );
    // 值变更
    const handleChange = (e: IData) => {
      isDebounce = true;
      debounceChange(e);
    };

    const handleKeyUp = (e: KeyboardEvent) => {
      if (e && e.code === 'Enter') {
        if (isDebounce) {
          awaitSearch = () => {
            inputRef.value.$el.dispatchEvent(e);
          };
        }
      }
    };

    /**
     * blur时马上抛值变更
     * @author lxm
     * @date 2023-03-06 06:36:23
     */
    const handleBlur = () => {
      blurCacheValue = inputRef.value.currentValue;
      emit('change', blurCacheValue);
    };

    // 自动聚焦
    if (props.autoFocus) {
      watch(inputRef, newVal => {
        if (newVal) {
          let input = newVal.$el.getElementsByTagName('input')[0];
          if (!input) {
            input = newVal.$el.getElementsByTagName('textarea')[0];
          }
          input.focus();
        }
      });
    }

    return {
      ns,
      rows,
      type,
      currentVal,
      handleChange,
      handleKeyUp,
      handleBlur,
      inputRef,
      autoSize,
    };
  },
  render() {
    return (
      <div
        class={[
          this.ns.b(),
          this.ns.is('textarea', Object.is(this.type, 'textarea')),
          this.disabled ? this.ns.m('disabled') : '',
          this.readonly ? this.ns.m('readonly') : '',
        ]}
      >
        {this.readonly ? (
          this.currentVal
        ) : (
          <i-input
            ref='inputRef'
            value={this.currentVal}
            placeholder={this.controller.placeHolder}
            type={this.type}
            rows={this.rows}
            on-on-change={this.handleChange}
            on-on-blur={this.handleBlur}
            nativeOnkeyup={this.handleKeyUp}
            class={this.ns.b('input')}
            disabled={this.disabled}
            autosize={this.autoSize}
          >
            {this.controller.model.unitName && (
              <i class={this.ns.e('unit')} slot='suffix'>
                {this.controller.model.unitName}
              </i>
            )}
          </i-input>
        )}
      </div>
    );
  },
});
