import React, { 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';
var PasswordInput = /*#__PURE__*/forwardRef(function (props, ref) {
  var _clsx2;

  var _useContext = useContext(ConfigProviderContext),
      prefixCls = _useContext.prefixCls,
      createNamespace = _useContext.createNamespace;

  var _createNamespace = createNamespace('password-input', prefixCls),
      bem = _createNamespace[0];

  var innerEffect = useRef(false);
  var inputRef = useRef(null);

  var _useSetState = useSetState({
    code: props.value || '',
    focused: props.autoFocus,
    inputType: props.type,
    inputMode: 'text'
  }),
      state = _useSetState[0],
      updateState = _useSetState[1];

  var codeArr = useMemo(function () {
    var _state$code;

    return (_state$code = state.code) == null ? void 0 : _state$code.toString().split('');
  }, [state.code]);
  var cursorIndex = useMemo(function () {
    return codeArr.length;
  }, [codeArr.length]);
  var length = props.length,
      onSubmit = props.onSubmit;

  var focus = function focus() {
    var _inputRef$current;

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

  var blur = function blur() {
    var _inputRef$current2;

    (_inputRef$current2 = inputRef.current) == null ? void 0 : _inputRef$current2.blur();
    updateState({
      focused: false
    });
  };

  var clear = function clear() {
    updateState({
      code: ''
    });
  };

  var formatValue = function formatValue(val, callback) {
    var _val;

    if (isDef(length) && ((_val = val) == null ? 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);
    }
  };

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

  var renderPoints = function renderPoints() {
    var Points = [];
    var mask = props.mask,
        gutter = props.gutter; // eslint-disable-next-line no-plusplus

    for (var i = 0; i < length; i++) {
      var _clsx;

      var _char = codeArr[i];
      var showBorder = i !== 0 && !gutter;
      var showCursor = state.focused && cursorIndex === i && !_char;
      var style = void 0;

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

      Points.push( /*#__PURE__*/React.createElement("li", {
        key: i,
        className: clsx((_clsx = {}, _clsx[BORDER_LEFT] = showBorder, _clsx[props.highlightClass] = props.highlightClass && _char && !props.mask, _clsx), bem('item', {
          focus: showCursor
        })),
        style: style
      }, mask ? /*#__PURE__*/React.createElement("i", {
        style: {
          visibility: _char ? 'visible' : 'hidden'
        }
      }) : _char, showCursor && /*#__PURE__*/React.createElement("div", {
        className: clsx(bem('cursor'))
      })));
    }

    return Points;
  };

  useUpdateEffect(function () {
    var _props$value;

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

    formatValue((_props$value = props.value) != null ? _props$value : '');
  }, [props.value]);
  useEffect(function () {
    if (state.code.length >= length) {
      var _inputRef$current3;

      inputRef == null ? void 0 : (_inputRef$current3 = inputRef.current) == null ? void 0 : _inputRef$current3.blur == null ? void 0 : _inputRef$current3.blur();
      onSubmit == null ? void 0 : onSubmit(state.code);
    } // eslint-disable-next-line react-hooks/exhaustive-deps

  }, [length, state.code]);
  useUpdateEffect(function () {
    if (props.type === 'number') {
      updateState({
        inputType: 'tel',
        inputMode: 'numeric'
      });
    } else {
      updateState({
        inputType: 'text'
      });
    }
  }, [props.type]);
  useImperativeHandle(ref, function () {
    return {
      focus: focus,
      blur: blur,
      clear: clear
    };
  });
  var info = props.errorInfo || props.info;
  return /*#__PURE__*/React.createElement("div", {
    className: clsx(bem(), props.className),
    style: props.style
  }, /*#__PURE__*/React.createElement("ul", {
    className: clsx(bem('security'), (_clsx2 = {}, _clsx2[BORDER_SURROUND] = !props.gutter, _clsx2))
  }, renderPoints(), /*#__PURE__*/React.createElement("input", {
    ref: inputRef,
    type: state.inputType,
    inputMode: state.inputMode,
    pattern: "[0-9]*",
    maxLength: props.length,
    value: state.code,
    autoComplete: "false",
    autoCorrect: "off",
    autoCapitalize: "off" // eslint-disable-next-line jsx-a11y/no-autofocus
    ,
    autoFocus: props.autoFocus,
    spellCheck: "false",
    onChange: handleChange,
    onFocus: function onFocus(e) {
      updateState({
        focused: true
      });
      props.onFocus == null ? void 0 : props.onFocus(e);
    },
    onBlur: function onBlur(e) {
      updateState({
        focused: false
      });
      props.onBlur == null ? void 0 : props.onBlur(e);
    }
  })), info ? /*#__PURE__*/React.createElement("div", {
    className: clsx(bem(props.errorInfo ? 'error-info' : 'info'))
  }, info) : null);
});
PasswordInput.defaultProps = {
  length: 6,
  gutter: 0,
  mask: true,
  type: 'text'
};
export default PasswordInput;