import * as React from 'react';
import HistoryNavigator from '../common/historyNavigator/historyNavigator.mjs';
import '../common/theme.mjs';
import '../common/direction.mjs';
import '../common/propsValues/control.mjs';
import '../common/propsValues/breakpoint.mjs';
import '../common/propsValues/size.mjs';
import '../common/propsValues/typography.mjs';
import '../common/propsValues/width.mjs';
import '../common/propsValues/type.mjs';
import '../common/propsValues/dateMode.mjs';
import '../common/propsValues/monthFormat.mjs';
import '../common/propsValues/position.mjs';
import '../common/propsValues/layouts.mjs';
import '../common/propsValues/status.mjs';
import '../common/propsValues/sentiment.mjs';
import '../common/propsValues/profileType.mjs';
import '../common/propsValues/variant.mjs';
import '../common/propsValues/scroll.mjs';
import '../common/propsValues/markdownNodeType.mjs';
import '../common/fileType.mjs';
import '@transferwise/icons';
import 'clsx';
import 'react-intl';
import '../common/closeButton/CloseButton.messages.mjs';
import 'react/jsx-runtime';
import formatWithPattern from '../common/textFormat/formatWithPattern/formatWithPattern.mjs';
import unformatWithPattern from '../common/textFormat/unformatWithPattern/unformatWithPattern.mjs';
import getCountOfSymbolsInSelection from '../common/textFormat/getCountOfSymbolsInSelection/getCountOfSymbolsInSelection.mjs';
import getCursorPositionAfterActionStroke from '../common/textFormat/getCursorPositionAfterKeystroke/getCursorPositionAfterKeystroke.mjs';
import { getDistanceToNextSymbol, getDistanceToPreviousSymbol } from '../common/textFormat/getDistanceToSymbol/getDistanceToSymbol.mjs';

class WithDisplayFormat extends React.Component {
  static defaultProps = {
    autoComplete: 'off',
    displayPattern: '',
    value: ''
  };
  constructor(props) {
    super(props);
    const unformattedValue = unformatWithPattern(props.value ?? '', props.displayPattern);
    this.state = {
      value: formatWithPattern(unformattedValue, props.displayPattern),
      historyNavigator: new HistoryNavigator(),
      prevDisplayPattern: props.displayPattern,
      triggerType: 'Initial',
      triggerEvent: null,
      selectionStart: 0,
      selectionEnd: 0,
      pastedLength: 0
    };
  }
  static getDerivedStateFromProps({
    displayPattern
  }, {
    prevDisplayPattern = displayPattern,
    value,
    historyNavigator
  }) {
    if (prevDisplayPattern !== displayPattern) {
      const unFormattedValue = unformatWithPattern(value, prevDisplayPattern);
      historyNavigator.reset();
      return {
        prevDisplayPattern: displayPattern,
        value: formatWithPattern(unFormattedValue, displayPattern),
        triggerType: null,
        triggerEvent: null,
        pastedLength: 0
      };
    }
    return null;
  }
  getUserAction = unformattedValue => {
    const {
      triggerEvent,
      triggerType,
      value
    } = this.state;
    const {
      displayPattern
    } = this.props;
    if (triggerEvent) {
      const charCode = String.fromCharCode(triggerEvent.which).toLowerCase();
      if (triggerType === 'Paste' || triggerType === 'Cut') {
        return triggerType;
      }
      if ((triggerEvent.ctrlKey || triggerEvent.metaKey) && charCode === 'z') {
        return triggerEvent.shiftKey ? 'Redo' : 'Undo';
      }
      // Detect mouse event redo
      if (triggerEvent.ctrlKey && charCode === 'd') {
        return 'Delete';
      }
      // Android Fix.
      if (typeof triggerEvent.key === 'undefined' && unformattedValue.length <= unformatWithPattern(value, displayPattern).length) {
        return 'Backspace';
      }
      return triggerEvent.key;
    }
    // triggerEvent can be null only in case of "autofilling" (via password manager extension or browser build-in one) events
    return 'Paste';
  };
  resetEvent = () => {
    this.setState({
      triggerType: 'Initial',
      triggerEvent: null,
      pastedLength: 0
    });
  };
  detectUndoRedo = event => {
    const charCode = String.fromCharCode(event.which).toLowerCase();
    if ((event.ctrlKey || event.metaKey) && charCode === 'z') {
      return event.shiftKey ? 'Redo' : 'Undo';
    }
    return null;
  };
  handleOnKeyDown = event => {
    event.persist();
    const {
      selectionStart,
      selectionEnd
    } = event.currentTarget;
    const {
      historyNavigator
    } = this.state;
    const {
      displayPattern
    } = this.props;
    // Unfortunately Undo and Redo don't trigger OnChange event so we need to handle some value logic here.
    let newFormattedValue = '';
    if (this.detectUndoRedo(event) === 'Undo') {
      newFormattedValue = formatWithPattern(historyNavigator.undo().toString(), displayPattern);
      this.setState({
        value: newFormattedValue,
        triggerType: 'Undo'
      });
    } else if (this.detectUndoRedo(event) === 'Redo') {
      newFormattedValue = formatWithPattern(historyNavigator.redo().toString(), displayPattern);
      this.setState({
        value: newFormattedValue,
        triggerType: 'Redo'
      });
    } else {
      this.setState({
        triggerEvent: event,
        triggerType: 'KeyDown',
        selectionStart: selectionStart ?? 0,
        selectionEnd: selectionEnd ?? 0
      });
    }
  };
  handleOnPaste = event => {
    const {
      displayPattern
    } = this.props;
    const pastedLength = unformatWithPattern(event.clipboardData.getData('Text'), displayPattern).length;
    this.setState({
      triggerType: 'Paste',
      pastedLength
    });
  };
  handleOnCut = () => {
    this.setState({
      triggerType: 'Cut'
    });
  };
  isKeyAllowed = action => {
    const {
      displayPattern
    } = this.props;
    const symbolsInPattern = displayPattern.split('').filter(character => character !== '*');
    return !symbolsInPattern.includes(action);
  };
  handleOnChange = event => {
    const {
      historyNavigator,
      triggerType
    } = this.state;
    const {
      displayPattern,
      onChange
    } = this.props;
    const {
      value
    } = event.target;
    let unformattedValue = unformatWithPattern(value, displayPattern);
    const action = this.getUserAction(unformattedValue);
    if (!this.isKeyAllowed(action) || triggerType === 'Undo' || triggerType === 'Redo') {
      return;
    }
    if (action === 'Backspace' || action === 'Delete') {
      unformattedValue = this.handleDelete(unformattedValue, action);
    }
    const newFormattedValue = formatWithPattern(unformattedValue, displayPattern);
    historyNavigator.add(unformattedValue);
    this.handleCursorPositioning(action);
    this.setState({
      value: newFormattedValue
    }, () => {
      this.resetEvent();
      if (onChange) {
        const broadcastValue = unformatWithPattern(newFormattedValue, displayPattern);
        onChange(broadcastValue);
      }
    });
  };
  handleOnBlur = event => {
    this.props.onBlur?.(unformatWithPattern(event.target.value, this.props.displayPattern));
  };
  handleOnFocus = event => {
    const {
      displayPattern,
      onFocus
    } = this.props;
    if (onFocus) {
      this.handleOnChange(event);
      onFocus(unformatWithPattern(event.target.value, displayPattern));
    }
  };
  handleDelete = (unformattedValue, action) => {
    const {
      displayPattern
    } = this.props;
    const {
      selectionStart,
      selectionEnd
    } = this.state;
    const newStack = [...unformattedValue];
    if (selectionStart === selectionEnd) {
      let startPosition = selectionStart - getCountOfSymbolsInSelection(0, selectionStart, displayPattern);
      let toDelete = 0;
      let count = getDistanceToNextSymbol(selectionStart, displayPattern);
      if (action === 'Backspace') {
        startPosition -= 1;
        count = getDistanceToPreviousSymbol(selectionStart, displayPattern);
      }
      if (startPosition >= 0 && count) {
        toDelete = 1;
      }
      newStack.splice(startPosition, toDelete);
    }
    return newStack.join('');
  };
  handleCursorPositioning = action => {
    const {
      displayPattern
    } = this.props;
    const {
      triggerEvent,
      selectionStart,
      selectionEnd,
      pastedLength
    } = this.state;
    const target = triggerEvent?.currentTarget;
    const cursorPosition = getCursorPositionAfterActionStroke(action, selectionStart, selectionEnd, displayPattern, pastedLength);
    setTimeout(() => {
      target?.setSelectionRange(cursorPosition, cursorPosition);
      this.setState({
        selectionStart: cursorPosition,
        selectionEnd: cursorPosition
      });
    }, 0);
  };
  render() {
    const {
      inputMode,
      className,
      id,
      name,
      placeholder,
      readOnly,
      required,
      minLength,
      maxLength,
      disabled,
      autoComplete
    } = this.props;
    const {
      value
    } = this.state;
    const renderProps = {
      inputMode,
      className,
      id,
      name,
      placeholder,
      readOnly,
      required,
      minLength,
      maxLength,
      disabled,
      autoComplete,
      value,
      onFocus: this.handleOnFocus,
      onBlur: this.handleOnBlur,
      onPaste: this.handleOnPaste,
      onKeyDown: this.handleOnKeyDown,
      onChange: this.handleOnChange,
      onCut: this.handleOnCut
    };
    return this.props.render(renderProps);
  }
}

export { WithDisplayFormat as default };
//# sourceMappingURL=WithDisplayFormat.mjs.map
