"use strict";var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;exports.__esModule = true;exports.Effect = void 0;exports.reducer = reducer;var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _lodash = _interopRequireDefault(require("lodash.debounce"));
var _lodash2 = _interopRequireDefault(require("lodash.isequal"));
var _globalObject = require("@skbkontur/global-object");

var _utils = require("../../lib/utils");
var _identifiers = require("../../lib/events/keyboard/identifiers");
var LayoutEvents = _interopRequireWildcard(require("../../lib/LayoutEvents"));




var _CustomComboBox = require("./CustomComboBox");
var _CustomComboBoxTypes = require("./CustomComboBoxTypes");


























































var DEBOUNCE_DELAY = 300;

var getValueString = function getValueString(value, valueToString) {
  return (0, _utils.isNonNullable)(value) ? valueToString(value) : '';
};

var Effect = exports.Effect = {
  search: function search(query) {return function (dispatch, getState, getProps, getInstance) {
      getInstance().search(query);
    };},
  debouncedSearch: (0, _lodash.default)(function (dispatch, getState, getProps, getInstance) {
    var searchEffect = Effect.search(getState().textValue);
    searchEffect(dispatch, getState, getProps, getInstance);
  }, DEBOUNCE_DELAY),
  cancelRequest: function cancelRequest(dispatch, getState, getProps, getInstance) {
    Effect.debouncedSearch.cancel();
    getInstance().cancelSearch();
  },
  blur: function blur(dispatch, getState, getProps) {
    var _getProps = getProps(),onBlur = _getProps.onBlur;
    if (onBlur) {
      onBlur();
    }
  },
  focus: function focus(dispatch, getState, getProps) {
    var _getProps2 = getProps(),onFocus = _getProps2.onFocus;
    if (onFocus) {
      onFocus();
    }
  },
  valueChange: function valueChange(value) {return function (dispatch, getState, getProps) {
      var _getProps3 = getProps(),onValueChange = _getProps3.onValueChange;
      if (onValueChange) {
        onValueChange(value);
      }
    };},
  valueClear: function valueClear(dispatch) {
    dispatch({ type: 'TextChange', value: '' });
  },
  unexpectedInput: function unexpectedInput(textValue, items) {return function (dispatch, getState, getProps) {
      var _getProps4 = getProps(),onUnexpectedInput = _getProps4.onUnexpectedInput,valueToString = _getProps4.valueToString;
      if (Array.isArray(items) && items.length === 1) {
        var singleItem = items[0];
        var valueContent = getValueString(singleItem, valueToString);

        if (valueContent === textValue) {
          dispatch({ type: 'ValueChange', value: singleItem, keepFocus: false });
          return;
        }
      }

      if (onUnexpectedInput) {
        var value = onUnexpectedInput(textValue);
        if (value !== undefined) {
          dispatch({ type: 'ValueChange', value: value, keepFocus: false });
        }
      }
    };},
  inputChange: function inputChange(dispatch, getState, getProps) {
    var _getProps5 = getProps(),onInputValueChange = _getProps5.onInputValueChange;
    var _getState = getState(),textValue = _getState.textValue;
    if (onInputValueChange) {
      var returnedValue = onInputValueChange(textValue);
      if (typeof returnedValue === 'string' && returnedValue !== textValue) {
        dispatch({ type: 'TextChange', value: returnedValue });
      }
    }
  },
  inputFocus: function inputFocus(dispatch, getState, getProps, getInstance) {
    var _getInstance = getInstance(),input = _getInstance.input;

    if (!input) {
      return;
    }

    input.focus();
    var inputNode = input.getNode();
    if (inputNode) {
      inputNode.scrollLeft = inputNode.scrollWidth;
      inputNode.scrollTop = inputNode.scrollHeight;
    }
  },
  highlightMenuItem: function highlightMenuItem(dispatch, getState, getProps, getInstance) {
    var _getProps6 = getProps(),value = _getProps6.value,itemToValue = _getProps6.itemToValue,valueToString = _getProps6.valueToString;
    var _getState2 = getState(),items = _getState2.items,focused = _getState2.focused,textValue = _getState2.textValue,requestStatus = _getState2.requestStatus;
    var _getInstance2 = getInstance(),menu = _getInstance2.menu;
    var valueString = getValueString(value, valueToString);

    if (!menu) {
      return;
    }

    if (!focused) {
      return;
    }

    var index = -1;
    if (items != null && items.length && (0, _utils.isNonNullable)(value)) {
      index = items.findIndex(function (x) {return itemToValue(x) === itemToValue(value);});
      menu.highlightItem(index);
    } else {
      menu.reset();
    }

    if (index >= 0) {
      // @ts-expect-error: Use of private property.
      _globalObject.globalObject.requestAnimationFrame == null || _globalObject.globalObject.requestAnimationFrame(function () {return menu == null ? void 0 : menu.scrollToSelected();});
      return;
    }

    var queryTextDifferenceOfSavedValue = textValue !== valueString;
    var needFocusToRefreshButton = requestStatus === _CustomComboBoxTypes.ComboBoxRequestStatus.Failed;
    if (queryTextDifferenceOfSavedValue || needFocusToRefreshButton) {
      _globalObject.globalObject.requestAnimationFrame == null || _globalObject.globalObject.requestAnimationFrame(function () {return menu == null ? void 0 : menu.highlightItem(0);});
    }
  },
  selectMenuItem: function selectMenuItem(event) {return function (dispatch, getState, getProps, getInstance) {
      var _getInstance3 = getInstance(),menu = _getInstance3.menu;
      if (menu) {
        menu.enter(event);
      }
    };},
  moveMenuHighlight: function moveMenuHighlight(direction) {return function (dispatch, getState, getProps, getInstance) {
      var _getInstance4 = getInstance(),menu = _getInstance4.menu;
      if (menu) {
        menu[direction]();
      }
    };},
  resetHighlightedMenuItem: function resetHighlightedMenuItem(dispatch, getState, getProps, getInstance) {
    var combobox = getInstance();

    if (combobox.menu && combobox.menu.hasHighlightedItem()) {
      combobox.menu.reset();
    }
  },
  reflow: function reflow() {
    LayoutEvents.emit();
  },
  selectInputText: function selectInputText(dispatch, getState, getProps, getInstance) {
    var combobox = getInstance();
    combobox.selectInputText();
  },
  inputKeyDown: function inputKeyDown(event) {return function (dispatch, getState, getProps) {
      var _getProps7 = getProps(),onInputKeyDown = _getProps7.onInputKeyDown;
      if (onInputKeyDown) {
        onInputKeyDown(event);
      }
    };}
};

var never = function never() {return null;};

function reducer(
state,
props,
action)
{
  switch (action.type) {
    case 'ValueChange':{
        var value = action.value,keepFocus = action.keepFocus;
        var textValue = getValueString(value, props.valueToString);
        if (keepFocus) {
          return [
          {
            opened: false,
            inputChanged: false,
            editing: true,
            items: null,
            textValue: textValue
          },
          [Effect.valueChange(value), Effect.cancelRequest, Effect.inputFocus]];

        }
        return [
        {
          opened: false,
          inputChanged: false,
          editing: false,
          items: null,
          textValue: textValue
        },
        [Effect.valueChange(value), Effect.cancelRequest]];

      }
    case 'TextChange':{
        var newState = {
          inputChanged: true,
          textValue: action.value
        };
        if (!action.value && !props.searchOnFocus) {
          return [(0, _extends2.default)({},

          newState, {
            opened: false,
            items: null }),

          [Effect.inputChange]];

        }
        return [newState, [Effect.debouncedSearch, Effect.inputChange]];
      }
    case 'KeyPress':{
        var e = action.event;
        var effects = [];
        var nextState = state;

        switch (true) {
          case (0, _identifiers.isKeyEnter)(e):
            if (!state.opened) {
              break;
            }
            e.preventDefault();
            effects.push(Effect.selectMenuItem(e));
            break;
          case (0, _identifiers.isKeyArrowVertical)(e):
            e.preventDefault();
            effects.push(Effect.moveMenuHighlight((0, _identifiers.isKeyArrowUp)(e) ? 'up' : 'down'));
            if (!state.opened) {
              effects.push(Effect.search(state.textValue));
            }
            break;
          case (0, _identifiers.isKeyEscape)(e):
            nextState = (0, _extends2.default)({},
            state, {
              items: null,
              opened: false });

            break;
        }
        return [nextState, [].concat(effects, [Effect.inputKeyDown(e)])];
      }
    case 'DidUpdate':{
        if ((0, _lodash2.default)(props.value, action.prevProps.value)) {
          return state;
        }

        if (action.fixValueChange) {
          var nextTextValue = getValueString(props.value, props.valueToString);

          if (!state.focused) {
            return [
            {
              editing: false,
              inputChanged: false,
              textValue: nextTextValue
            },
            [Effect.cancelRequest]];

          }

          if (state.focused && state.opened) {
            return [(0, _extends2.default)({}, state, { textValue: nextTextValue }), [Effect.cancelRequest, Effect.search(nextTextValue)]];
          }

          if (state.focused) {
            return (0, _extends2.default)({},
            state, {
              textValue: nextTextValue });

          }
        }

        return {
          opened: false,
          textValue: state.editing ? state.textValue : getValueString(props.value, props.valueToString)
        };
      }
    case 'Mount':{
        return {
          textValue: getValueString(props.value, props.valueToString)
        };
      }
    case 'Focus':{
        var _newState = {
          focused: true,
          editing: true
        };
        if (!action.searchOnFocus) {
          return [_newState, [Effect.focus]];
        }
        if (state.editing) {
          return [_newState, [Effect.search(state.textValue), Effect.focus]];
        }
        return [_newState, [Effect.search(''), Effect.focus, Effect.selectInputText]];
      }
    case 'InputClick':{
        var _newState2 = {
          inputChanged: false
        };
        if (!state.opened && props.searchOnFocus) {
          return [_newState2, [Effect.search('')]];
        }
        return state;
      }
    case 'ClearCrossClick':{
        var _newState3 = {
          editing: true,
          loading: true
        };
        return [_newState3, [Effect.valueClear, Effect.focus, Effect.search('')]];
      }
    case 'Blur':{
        var inputChanged = state.inputChanged,items = state.items;
        if (!inputChanged) {
          return [
          {
            focused: false,
            opened: false,
            items: null,
            editing: false
          },
          [Effect.blur, Effect.cancelRequest]];

        }

        return [
        {
          focused: false,
          opened: false,
          items: null
        },
        [Effect.blur, Effect.cancelRequest, Effect.unexpectedInput(state.textValue, items)]];

      }
    case 'Reset':{
        return _CustomComboBox.DefaultState;
      }
    case 'Open':{
        return { opened: true };
      }
    case 'Close':{
        return { opened: false, items: null };
      }
    case 'Search':{
        return [state, [Effect.search(action.query)]];
      }
    case 'RequestItems':{
        return {
          loading: true,
          opened: true,
          requestStatus: _CustomComboBoxTypes.ComboBoxRequestStatus.Pending
        };
      }
    case 'ReceiveItems':{
        var shouldResetMenuHighlight = state.textValue === '';
        return [
        {
          loading: false,
          opened: true,
          items: action.items,
          requestStatus: _CustomComboBoxTypes.ComboBoxRequestStatus.Success
        },
        [shouldResetMenuHighlight ? Effect.resetHighlightedMenuItem : Effect.highlightMenuItem, Effect.reflow]];

      }
    case 'RequestFailure':{
        return [
        {
          loading: false,
          opened: true,
          items: null,
          requestStatus: _CustomComboBoxTypes.ComboBoxRequestStatus.Failed,
          repeatRequest: action.repeatRequest
        },
        [Effect.highlightMenuItem]];

      }
    case 'CancelRequest':{
        return {
          loading: false,
          requestStatus: _CustomComboBoxTypes.ComboBoxRequestStatus.Unknown
        };
      }
    default:{
        never();
      }
  }
  return state;
}