import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useEffect, useRef, forwardRef, useImperativeHandle, useMemo, useContext } from 'react';
import clsx from 'clsx';
import { isFunction, formatNumber, isDef, addUnit } from '../utils';
import { useSetState, useUpdateEffect } from '../hooks';
import { BORDER_LEFT, BORDER_SURROUND } from '../utils/constant';
import ConfigProviderContext from '../config-provider/ConfigProviderContext';
const PasswordInput = forwardRef((props, ref) => {
  const {
    prefixCls,
    createNamespace
  } = useContext(ConfigProviderContext);
  const [bem] = createNamespace('password-input', prefixCls);
  const innerEffect = useRef(false);
  const inputRef = useRef(null);
  const [state, updateState] = useSetState({
    code: props.value || '',
    focused: props.autoFocus,
    inputType: props.type,
    inputMode: 'text'
  });
  const codeArr = useMemo(() => {
    var _a;

    return (_a = state.code) === null || _a === void 0 ? void 0 : _a.toString().split('');
  }, [state.code]);
  const cursorIndex = useMemo(() => codeArr.length, [codeArr.length]);
  const {
    length,
    onSubmit
  } = props;

  const focus = () => {
    var _a;

    (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
    updateState({
      focused: true
    });
  };

  const blur = () => {
    var _a;

    (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.blur();
    updateState({
      focused: false
    });
  };

  const clear = () => {
    updateState({
      code: ''
    });
  };

  const formatValue = (val, callback) => {
    if (isDef(length) && (val === null || val === void 0 ? void 0 : val.length) > +length) {
      val = val.slice(0, length);
    }

    if (props.type === 'number') {
      val = formatNumber(val, false, false);
    }

    if (isFunction(props.validator)) {
      if (props.validator(val)) {
        updateState({
          code: val
        });
        if (isFunction(callback)) callback(val);
      }
    } else {
      updateState({
        code: val
      });
      if (isFunction(callback)) callback(val);
    }
  };

  const handleChange = e => {
    const val = e.target.value || '';
    innerEffect.current = true;
    formatValue(val, props.onChange);
  };

  const renderPoints = () => {
    const Points = [];
    const {
      mask,
      gutter
    } = props; // eslint-disable-next-line no-plusplus

    for (let i = 0; i < length; i++) {
      const char = codeArr[i];
      const showBorder = i !== 0 && !gutter;
      const showCursor = state.focused && cursorIndex === i && !char;
      let style;

      if (i !== 0 && gutter) {
        style = {
          marginLeft: addUnit(gutter)
        };
      }

      Points.push(_jsxs("li", Object.assign({
        className: clsx({
          [BORDER_LEFT]: showBorder,
          [props.highlightClass]: props.highlightClass && char && !props.mask
        }, bem('item', {
          focus: showCursor
        })),
        style: style
      }, {
        children: [mask ? _jsx("i", {
          style: {
            visibility: char ? 'visible' : 'hidden'
          }
        }) : char, showCursor && _jsx("div", {
          className: clsx(bem('cursor'))
        })]
      }), i));
    }

    return Points;
  };

  useUpdateEffect(() => {
    var _a;

    if (innerEffect.current) {
      innerEffect.current = false;
      return;
    }

    formatValue((_a = props.value) !== null && _a !== void 0 ? _a : '');
  }, [props.value]);
  useEffect(() => {
    var _a, _b;

    if (state.code.length >= length) {
      (_b = (_a = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _a === void 0 ? void 0 : _a.blur) === null || _b === void 0 ? void 0 : _b.call(_a);
      onSubmit === null || onSubmit === void 0 ? void 0 : onSubmit(state.code);
    } // eslint-disable-next-line react-hooks/exhaustive-deps

  }, [length, state.code]);
  useUpdateEffect(() => {
    if (props.type === 'number') {
      updateState({
        inputType: 'tel',
        inputMode: 'numeric'
      });
    } else {
      updateState({
        inputType: 'text'
      });
    }
  }, [props.type]);
  useImperativeHandle(ref, () => ({
    focus,
    blur,
    clear
  }));
  const info = props.errorInfo || props.info;
  return _jsxs("div", Object.assign({
    className: clsx(bem(), props.className),
    style: props.style
  }, {
    children: [_jsxs("ul", Object.assign({
      className: clsx(bem('security'), {
        [BORDER_SURROUND]: !props.gutter
      })
    }, {
      children: [renderPoints(), _jsx("input", {
        ref: inputRef,
        type: state.inputType,
        inputMode: state.inputMode,
        pattern: "[0-9]*",
        maxLength: props.length,
        value: state.code,
        autoComplete: "false",
        autoCorrect: "off",
        autoCapitalize: "off",
        autoFocus: props.autoFocus,
        spellCheck: "false",
        onChange: handleChange,
        onFocus: e => {
          var _a;

          updateState({
            focused: true
          });
          (_a = props.onFocus) === null || _a === void 0 ? void 0 : _a.call(props, e);
        },
        onBlur: e => {
          var _a;

          updateState({
            focused: false
          });
          (_a = props.onBlur) === null || _a === void 0 ? void 0 : _a.call(props, e);
        }
      })]
    })), info ? _jsx("div", Object.assign({
      className: clsx(bem(props.errorInfo ? 'error-info' : 'info'))
    }, {
      children: info
    })) : null]
  }));
});
PasswordInput.defaultProps = {
  length: 6,
  gutter: 0,
  mask: true,
  type: 'text'
};
export default PasswordInput;