'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var _defineProperty = require('@babel/runtime/helpers/defineProperty');
var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
var _toConsumableArray = require('@babel/runtime/helpers/toConsumableArray');
require('core-js/modules/es.array.concat.js');
require('core-js/modules/es.array.find-index.js');
require('core-js/modules/es.array.map.js');
require('core-js/modules/es.array.splice.js');
require('core-js/modules/es.object.to-string.js');
require('core-js/modules/es.regexp.exec.js');
require('core-js/modules/web.dom-collections.for-each.js');
var React = require('react');
var PropTypes = require('prop-types');
var classnames = require('classnames');
var Settings = require('../../constants/Settings.js');
var useMerged = require('../../hooks/useMerged.js');
var Button = require('../Button/Button.js');
var KeyCodeConstants = require('../../constants/KeyCodeConstants.js');
var iconsReact = require('@carbon/icons-react');

function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }

var _defineProperty__default = /*#__PURE__*/_interopDefault(_defineProperty);
var _slicedToArray__default = /*#__PURE__*/_interopDefault(_slicedToArray);
var _toConsumableArray__default = /*#__PURE__*/_interopDefault(_toConsumableArray);
var React__default = /*#__PURE__*/_interopDefault(React);
var PropTypes__default = /*#__PURE__*/_interopDefault(PropTypes);
var classnames__default = /*#__PURE__*/_interopDefault(classnames);

var iotPrefix = Settings.settings.iotPrefix;
var propTypes = {
  className: PropTypes__default.default.string,
  testId: PropTypes__default.default.string,
  i18n: PropTypes__default.default.shape({
    previous: PropTypes__default.default.string,
    next: PropTypes__default.default.string
  }),
  /** Optional default selected item */
  defaultSelectedId: PropTypes__default.default.string,
  /** Optional handler that is called whenever value is updated */
  onChange: PropTypes__default.default.func,
  /** Optional handler that is called whenever item is clicked */
  onClick: PropTypes__default.default.func,
  /** Optional handler that is called whenever right arrow is clicked */
  onRightArrowClick: PropTypes__default.default.func,
  /** Optional handler that is called whenever left arrow is clicked */
  onLeftArrowClick: PropTypes__default.default.func,
  /** Array of items to render in the spinning list */
  list: PropTypes__default.default.arrayOf(PropTypes__default.default.shape({
    id: PropTypes__default.default.string,
    value: PropTypes__default.default.string
  })),
  /** Optional tag name to use instead of ul */
  containerElement: PropTypes__default.default.string
};

// istanbul ignore next
var defaultProps = {
  className: undefined,
  testId: 'list-spinner',
  i18n: {
    previous: 'Previous item',
    next: 'Next item'
  },
  defaultSelectedId: undefined,
  onChange: function onChange() {},
  onClick: function onClick() {},
  onRightArrowClick: function onRightArrowClick() {},
  onLeftArrowClick: function onLeftArrowClick() {},
  list: [],
  containerElement: 'ul'
};

/**
 *
 * @param {*} arr - the array to opperate on
 * @param {*} index - the index of the item to move
 * @returns array - new array with the chosen index as 3 item in array
 */
function moveToSecondIndex(arr, index) {
  var newArr = _toConsumableArray__default.default(arr);
  var removed;
  if (index > 2) {
    // 6 - 2
    removed = newArr.splice(0, index - 2);
    newArr.push.apply(newArr, _toConsumableArray__default.default(removed));
  }
  if (index < 2) {
    var amnt = 2 - index;
    // 6 - 2
    removed = newArr.splice(-amnt, amnt);
    newArr.unshift.apply(newArr, _toConsumableArray__default.default(removed));
  }
  return newArr;
}
var ListSpinner = /*#__PURE__*/React__default.default.forwardRef(function (_ref, ref) {
  var className = _ref.className,
    testId = _ref.testId,
    i18n = _ref.i18n,
    defaultSelectedId = _ref.defaultSelectedId,
    onChange = _ref.onChange,
    onClick = _ref.onClick,
    onRightArrowClick = _ref.onRightArrowClick,
    onLeftArrowClick = _ref.onLeftArrowClick,
    list = _ref.list,
    ContainerElement = _ref.containerElement;
  var containerRef = React.useRef();
  var contentRef = React.useRef();
  var touch = React.useRef(false);
  var ticking = React.useRef(false);
  var scrollEvent = React.useRef(false);
  var scrollPosition = React.useRef();
  var timer = React.useRef();
  var _useState = React.useState(list),
    _useState2 = _slicedToArray__default.default(_useState, 2),
    listItems = _useState2[0],
    setListItems = _useState2[1];
  var _useState3 = React.useState(defaultSelectedId),
    _useState4 = _slicedToArray__default.default(_useState3, 2),
    selectedId = _useState4[0],
    setSelectedId = _useState4[1];
  var _useMerged = useMerged(defaultProps.i18n, i18n),
    previous = _useMerged.previous,
    next = _useMerged.next;
  React.useEffect(function () {
    setSelectedId(defaultSelectedId);
  }, [defaultSelectedId]);
  React.useEffect(function () {
    var index = list.findIndex(function (i) {
      return i.id === selectedId;
    });
    var newList = moveToSecondIndex(list, index);
    setListItems(newList);
    onChange(selectedId);
    /* eslint-disable-next-line react-hooks/exhaustive-deps */
  }, [onChange, selectedId]);
  var observerRef = React__default.default.useRef();
  React.useEffect(function () {
    var _window;
    // Create a new observer
    if ((_window = window) !== null && _window !== void 0 && _window.IntersectionObserver) {
      observerRef.current = new IntersectionObserver(function (entries) {
        entries.forEach(function (entry) {
          if (entry.isIntersecting && scrollEvent.current) {
            clearTimeout(timer.current);
            timer.current = setTimeout(setSelectedId(entry.target.childNodes[0].id), 800);
          }
        });
      }, {
        root: containerRef.current,
        rootMargin: '-50% 0% -50% 0%',
        threshold: 0
      });
    }
    return function () {
      var _observerRef$current;
      return (_observerRef$current = observerRef.current) === null || _observerRef$current === void 0 ? void 0 : _observerRef$current.disconnect();
    };
  }, []);
  var handleWheel = function handleWheel(e) {
    e.persist();
    scrollEvent.current = true;
    if (!ticking.current) {
      /* eslint-disable func-names */
      setTimeout(function () {
        return setTimeout(function () {
          if (e.deltaY < 0) {
            setSelectedId(function (prev) {
              var prevIndex = list.findIndex(function (i) {
                return i.id === prev;
              });
              var val = prevIndex > 0 ? list[prevIndex - 1].id : list[list.length - 1].id;
              setTimeout(function () {
                return onClick(val);
              });
              return val;
            });
          } else {
            setSelectedId(function (prev) {
              var prevIndex = list.findIndex(function (i) {
                return i.id === prev;
              });
              var val = prevIndex === list.indexOf(list[list.length - 1]) ? list[0].id : list[prevIndex + 1].id;
              setTimeout(function () {
                return onClick(val);
              });
              return val;
            });
          }
          ticking.current = false;
        });
      }, 100);
      ticking.current = true;
    }
  };
  var handleTouchMove = function handleTouchMove(e) {
    e.persist();
    scrollEvent.current = true;
    /* istanbul ignore else */
    if (!ticking.current) {
      /* eslint-disable func-names */
      setTimeout(function () {
        setTimeout(function () {
          if (scrollPosition.current - e.touches[0].pageY < 0) {
            setSelectedId(function (prev) {
              var prevIndex = list.findIndex(function (i) {
                return i.id === prev;
              });
              var val = prevIndex > 0 ? list[prevIndex - 1].id : list[list.length - 1].id;
              setTimeout(function () {
                return onClick(val);
              });
              return val;
            });
          } else {
            setSelectedId(function (prev) {
              var prevIndex = list.findIndex(function (i) {
                return i.id === prev;
              });
              var val = prevIndex === list.indexOf(list[list.length - 1]) ? list[0].id : list[prevIndex + 1].id;
              setTimeout(function () {
                return onClick(val);
              });
              return val;
            });
          }
          scrollPosition.current = e.touches[0].pageY;
          ticking.current = false;
          touch.current = false;
        });
      }, 100);
      ticking.current = true;
    }
  };
  var handleTouchStart = function handleTouchStart(e) {
    e.persist();
    scrollPosition.current = e.touches[0].pageY;
    touch.current = true;
  };

  // eslint-disable-next-line consistent-return
  var handleKeyPress = function handleKeyPress(e) {
    e.persist();
    // istanbul ignore else
    if (e.target.id.length === 2) {
      // istanbul ignore else
      if (e.key === KeyCodeConstants.keyboardKeys.UP) {
        e.preventDefault();
        setSelectedId(function (prev) {
          var prevIndex = list.findIndex(function (i) {
            return i.id === prev;
          });
          var val = prevIndex > 0 ? list[prevIndex - 1].id : list[list.length - 1].id;
          setTimeout(function () {
            return onClick(val);
          });
          return val;
        });
        setTimeout(function () {
          return contentRef.current.childNodes[0].focus();
        });
        return false;
      }
      // istanbul ignore else
      if (e.key === KeyCodeConstants.keyboardKeys.DOWN) {
        e.preventDefault();
        setSelectedId(function (prev) {
          var prevIndex = list.findIndex(function (i) {
            return i.id === prev;
          });
          var val = prevIndex === list.indexOf(list[list.length - 1]) ? list[0].id : list[prevIndex + 1].id;
          setTimeout(function () {
            return onClick(val);
          });
          return val;
        });
        setTimeout(function () {
          return contentRef.current.childNodes[0].focus();
        });
        return false;
      }
      // istanbul ignore else
      if (e.key === KeyCodeConstants.keyboardKeys.RIGHT) {
        onRightArrowClick(e);
      }
      // istanbul ignore else
      if (e.key === KeyCodeConstants.keyboardKeys.LEFT) {
        onLeftArrowClick(e);
      }
    }

    // istanbul ignore else
    if (/\s/.test(e.key) || e.key === 'Enter') {
      // istanbul ignore else
      if (e.currentTarget.id === "".concat(iotPrefix, "--list-spinner__btn--up")) {
        setSelectedId(function (prev) {
          var prevIndex = list.findIndex(function (i) {
            return i.id === prev;
          });
          var val = prevIndex > 0 ? list[prevIndex - 1].id : list[list.length - 1].id;
          setTimeout(function () {
            return onClick(val);
          });
          return val;
        });
      }
      // istanbul ignore else
      if (e.currentTarget.id === "".concat(iotPrefix, "--list-spinner__btn--down")) {
        setSelectedId(function (prev) {
          var prevIndex = list.findIndex(function (i) {
            return i.id === prev;
          });
          var val = prevIndex === list.indexOf(list[list.length - 1]) ? list[0].id : list[prevIndex + 1].id;
          setTimeout(function () {
            return onClick(val);
          });
          return val;
        });
      }
    }
  };
  var handleClick = React.useCallback(function (e) {
    e.persist();
    e.preventDefault();
    scrollEvent.current = false;
    if (e.currentTarget.id === "".concat(iotPrefix, "--list-spinner__btn--up")) {
      setSelectedId(function (prev) {
        var prevIndex = list.findIndex(function (i) {
          return i.id === prev;
        });
        var val = prevIndex > 0 ? list[prevIndex - 1].id : list[list.length - 1].id;
        setTimeout(function () {
          return onClick(val);
        });
        return val;
      });
    } else if (e.currentTarget.id === "".concat(iotPrefix, "--list-spinner__btn--down")) {
      setSelectedId(function (prev) {
        var prevIndex = list.findIndex(function (i) {
          return i.id === prev;
        });
        var val = prevIndex === list.indexOf(list[list.length - 1]) ? list[0].id : list[prevIndex + 1].id;
        setTimeout(function () {
          return onClick(val);
        });
        return val;
      });
    } else {
      setSelectedId(e.currentTarget.id);
      onClick(e.currentTarget.id);
    }
    e.currentTarget.focus();
  }, [list, onClick]);
  var renderItems = listItems.map(function (el) {
    return /*#__PURE__*/React__default.default.createElement("li", {
      "data-testid": "".concat(testId, "-list-item"),
      ref: function ref(node) {
        // Once component mounts tell our observer to observe it
        if (node) {
          if (el.value === selectedId) {
            contentRef.current = node;
          }
          setTimeout(function () {
            var _observerRef$current2;
            return (_observerRef$current2 = observerRef.current) === null || _observerRef$current2 === void 0 ? void 0 : _observerRef$current2.observe(node);
          }, 0);
        }
      },
      className: classnames__default.default("".concat(iotPrefix, "--list-spinner__list-item"), _defineProperty__default.default({}, "".concat(iotPrefix, "--list-spinner__list-item--selected"), el.id === selectedId)),
      key: el.id,
      id: "".concat(el.id, "-list-item"),
      "data-selected": el.value === selectedId
    }, /*#__PURE__*/React__default.default.createElement(Button, {
      ref: el.id === selectedId ? ref : null,
      testId: el.id === selectedId ? "".concat(testId, "-selected-item") : el.id,
      id: el.id,
      tabIndex: -1,
      kind: "ghost",
      iconDescription: el.value,
      onMouseDown: handleClick
    }, el.value));
  });
  return /*#__PURE__*/React__default.default.createElement("div", {
    "data-testid": testId,
    className: classnames__default.default("".concat(iotPrefix, "--list-spinner__section"), _defineProperty__default.default({}, className, className))
  }, /*#__PURE__*/React__default.default.createElement(Button, {
    tabIndex: -1,
    testId: "".concat(testId, "-prev-btn"),
    id: "".concat(iotPrefix, "--list-spinner__btn--up"),
    onMouseDown: handleClick,
    iconDescription: previous,
    className: "".concat(iotPrefix, "--list-spinner__btn ").concat(className, "-spinner__btn"),
    renderIcon: iconsReact.ChevronUp,
    kind: "ghost",
    onKeyDown: handleKeyPress
  }), /*#__PURE__*/React__default.default.createElement("div", {
    className: "".concat(iotPrefix, "--list-spinner__list-container ").concat(className, "-spinner__list-container")
  }, /*#__PURE__*/React__default.default.createElement(ContainerElement, {
    "data-testid": "".concat(testId, "-list"),
    ref: containerRef,
    className: "".concat(iotPrefix, "--list-spinner__list ").concat(className, "-spinner__list"),
    onWheel: handleWheel,
    onTouchStart: handleTouchStart,
    onTouchMove: handleTouchMove,
    onKeyDown: handleKeyPress
  }, renderItems)), /*#__PURE__*/React__default.default.createElement(Button, {
    testId: "".concat(testId, "-next-btn"),
    tabIndex: -1,
    id: "".concat(iotPrefix, "--list-spinner__btn--down"),
    onMouseDown: handleClick,
    className: "".concat(iotPrefix, "--list-spinner__btn ").concat(className, "-spinner__btn"),
    iconDescription: next,
    renderIcon: iconsReact.ChevronDown,
    kind: "ghost",
    onKeyDown: handleKeyPress
  }));
});
ListSpinner.propTypes = propTypes;
ListSpinner.defaultProps = defaultProps;
ListSpinner.__docgenInfo = {
  "description": "",
  "methods": [],
  "displayName": "ListSpinner",
  "props": {
    "className": {
      "defaultValue": {
        "value": "undefined",
        "computed": true
      },
      "description": "",
      "type": {
        "name": "string"
      },
      "required": false
    },
    "testId": {
      "defaultValue": {
        "value": "'list-spinner'",
        "computed": false
      },
      "description": "",
      "type": {
        "name": "string"
      },
      "required": false
    },
    "i18n": {
      "defaultValue": {
        "value": "{\n  previous: 'Previous item',\n  next: 'Next item',\n}",
        "computed": false
      },
      "description": "",
      "type": {
        "name": "shape",
        "value": {
          "previous": {
            "name": "string",
            "required": false
          },
          "next": {
            "name": "string",
            "required": false
          }
        }
      },
      "required": false
    },
    "defaultSelectedId": {
      "defaultValue": {
        "value": "undefined",
        "computed": true
      },
      "description": "Optional default selected item",
      "type": {
        "name": "string"
      },
      "required": false
    },
    "onChange": {
      "defaultValue": {
        "value": "() => {}",
        "computed": false
      },
      "description": "Optional handler that is called whenever value is updated",
      "type": {
        "name": "func"
      },
      "required": false
    },
    "onClick": {
      "defaultValue": {
        "value": "() => {}",
        "computed": false
      },
      "description": "Optional handler that is called whenever item is clicked",
      "type": {
        "name": "func"
      },
      "required": false
    },
    "onRightArrowClick": {
      "defaultValue": {
        "value": "() => {}",
        "computed": false
      },
      "description": "Optional handler that is called whenever right arrow is clicked",
      "type": {
        "name": "func"
      },
      "required": false
    },
    "onLeftArrowClick": {
      "defaultValue": {
        "value": "() => {}",
        "computed": false
      },
      "description": "Optional handler that is called whenever left arrow is clicked",
      "type": {
        "name": "func"
      },
      "required": false
    },
    "list": {
      "defaultValue": {
        "value": "[]",
        "computed": false
      },
      "description": "Array of items to render in the spinning list",
      "type": {
        "name": "arrayOf",
        "value": {
          "name": "shape",
          "value": {
            "id": {
              "name": "string",
              "required": false
            },
            "value": {
              "name": "string",
              "required": false
            }
          }
        }
      },
      "required": false
    },
    "containerElement": {
      "defaultValue": {
        "value": "'ul'",
        "computed": false
      },
      "description": "Optional tag name to use instead of ul",
      "type": {
        "name": "string"
      },
      "required": false
    }
  }
};
var ListSpinner$1 = ListSpinner;

exports.default = ListSpinner$1;
exports.moveToSecondIndex = moveToSecondIndex;
