'use strict';

var React = require('react');
var historyNavigator = require('../common/historyNavigator/historyNavigator.js');
require('../common/theme.js');
require('../common/direction.js');
require('../common/propsValues/control.js');
require('../common/propsValues/breakpoint.js');
require('../common/propsValues/size.js');
require('../common/propsValues/typography.js');
require('../common/propsValues/width.js');
require('../common/propsValues/type.js');
require('../common/propsValues/dateMode.js');
require('../common/propsValues/monthFormat.js');
require('../common/propsValues/position.js');
require('../common/propsValues/layouts.js');
require('../common/propsValues/status.js');
require('../common/propsValues/sentiment.js');
require('../common/propsValues/profileType.js');
require('../common/propsValues/variant.js');
require('../common/propsValues/scroll.js');
require('../common/propsValues/markdownNodeType.js');
require('../common/fileType.js');
require('@transferwise/icons');
require('clsx');
require('react-intl');
require('../common/closeButton/CloseButton.messages.js');
require('react/jsx-runtime');
var formatWithPattern = require('../common/textFormat/formatWithPattern/formatWithPattern.js');
var unformatWithPattern = require('../common/textFormat/unformatWithPattern/unformatWithPattern.js');
var getCountOfSymbolsInSelection = require('../common/textFormat/getCountOfSymbolsInSelection/getCountOfSymbolsInSelection.js');
var getCursorPositionAfterKeystroke = require('../common/textFormat/getCursorPositionAfterKeystroke/getCursorPositionAfterKeystroke.js');
var getDistanceToSymbol = require('../common/textFormat/getDistanceToSymbol/getDistanceToSymbol.js');

function _interopNamespace(e) {
    if (e && e.__esModule) return e;
    var n = Object.create(null);
    if (e) {
        Object.keys(e).forEach(function (k) {
            if (k !== 'default') {
                var d = Object.getOwnPropertyDescriptor(e, k);
                Object.defineProperty(n, k, d.get ? d : {
                    enumerable: true,
                    get: function () { return e[k]; }
                });
            }
        });
    }
    n.default = e;
    return Object.freeze(n);
}

var React__namespace = /*#__PURE__*/_interopNamespace(React);

class WithDisplayFormat extends React__namespace.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 = getDistanceToSymbol.getDistanceToNextSymbol(selectionStart, displayPattern);
      if (action === 'Backspace') {
        startPosition -= 1;
        count = getDistanceToSymbol.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 = getCursorPositionAfterKeystroke(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);
  }
}

module.exports = WithDisplayFormat;
//# sourceMappingURL=WithDisplayFormat.js.map
