import React, { useEffect } from 'react';
import { useIMask } from 'react-imask';
import {
  SingleLineText,
  SingleLineTextProps,
} from '../SingleLineText/SingleLineText';

export interface MaskedSingleLineTextProps
  extends Omit<SingleLineTextProps, 'onChange' | 'type' | 'value' | 'isSet'> {
  /** Expression to be used as a validator.
   * Refer https://imask.js.org/guide.html#masked-pattern for examples
   */
  mask: string;

  /** Placeholder character for the mask */
  placeholderChar?: string;

  /** Current value the form control has */
  value?: string;

  /** Whether the mask should not be shown by default. (default: true) */
  lazy?: boolean;

  /** Whether new inputs should overwrite existing text. (default: false) */
  overwrite?: boolean;

  /** Raised when the value has changed */
  onChange: (value: string) => unknown;
}

export const MaskedSingleLineText: React.FC<MaskedSingleLineTextProps> = ({
  onChange,
  mask,
  placeholderChar = '_',
  value: formikValue = '',
  lazy = true,
  overwrite = false,
  ...props
}) => {
  const { ref, maskRef } = useIMask(
    { mask, placeholderChar, lazy, overwrite },
    {
      onAccept: (value, _ref, e) => {
        // OnChange shouldn't be used https://github.com/uNmAnNeR/imaskjs/issues/318
        // OnAccept fires during initial load making the form dirty. However, the synthetic event is not
        // present when this happens so we check for the event to see if it's actually a keyboard event
        // that triggered onAccept.
        if (e) {
          onChange(value);
        }
      },
    },
  );

  useEffect(() => {
    maskRef.current.value = formikValue as string;
  }, [formikValue, maskRef]);

  return <SingleLineText innerRef={ref} type="text" {...props} />;
};
