"use strict";

exports.__esModule = true;
exports.default = void 0;
var _findLastIndex2 = _interopRequireDefault(require("lodash/fp/findLastIndex"));
var _findIndex2 = _interopRequireDefault(require("lodash/fp/findIndex"));
var _head2 = _interopRequireDefault(require("lodash/fp/head"));
var _reduce2 = _interopRequireDefault(require("lodash/fp/reduce"));
var _toPairs2 = _interopRequireDefault(require("lodash/fp/toPairs"));
var _pipe2 = _interopRequireDefault(require("lodash/fp/pipe"));
var _last2 = _interopRequireDefault(require("lodash/fp/last"));
var _sum2 = _interopRequireDefault(require("lodash/fp/sum"));
var _map2 = _interopRequireDefault(require("lodash/fp/map"));
var _getOr2 = _interopRequireDefault(require("lodash/fp/getOr"));
var _get2 = _interopRequireDefault(require("lodash/fp/get"));
var _throttle2 = _interopRequireDefault(require("lodash/fp/throttle"));
var _debounce2 = _interopRequireDefault(require("lodash/fp/debounce"));
var _react = _interopRequireDefault(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _novaIcons = require("@coorpacademy/nova-icons");
var _provider = _interopRequireDefault(require("../../../atom/provider"));
var _card = _interopRequireWildcard(require("../../card"));
var _learningPriorityCard = _interopRequireDefault(require("../../learning-priority-card"));
var _icon = _interopRequireDefault(require("../../../atom/icon"));
var _style = _interopRequireDefault(require("./style.css"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
const ShowMoreLink = props => {
  const {
    onShowMore,
    showMore,
    className
  } = props;
  return /*#__PURE__*/_react.default.createElement("div", {
    className: className,
    onClick: onShowMore
  }, showMore);
};
ShowMoreLink.contextTypes = {
  skin: _provider.default.childContextTypes.skin
};
ShowMoreLink.propTypes = process.env.NODE_ENV !== "production" ? {
  onShowMore: _propTypes.default.func,
  showMore: _propTypes.default.string,
  className: _propTypes.default.string
} : {};
const IconView = (props, context) => {
  const {
    skin
  } = context;
  const {
    contentType
  } = props;
  const ICONS = {
    chapter: _novaIcons.NovaCompositionCoorpacademyTimer,
    course: _novaIcons.NovaSolidContentContentBook1
  };
  if (!contentType) {
    return null;
  }
  const dark = (0, _get2.default)('common.dark', skin);
  const IconType = ICONS[contentType];
  return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(IconType, {
    style: {
      color: dark
    },
    className: _style.default.icon,
    "data-contenttype": contentType
  }));
};
const computeWidth = card => {
  switch (card && card.type) {
    case 'chapter':
      return 219;
    default:
      return 272;
  }
};
const nextPage = (page, maxPages) => {
  if (page < 0) return maxPages;
  if (page > maxPages) return 0;
  return page;
};
IconView.propTypes = process.env.NODE_ENV !== "production" ? {
  contentType: _propTypes.default.string
} : {};
class CardsList extends _react.default.PureComponent {
  /**
   * IMPORTANT: update prop-types.ts too, 1st a migration of tests
   * is intended, then, a TS + functional refactor is planned.
   */

  static contextTypes = {
    skin: _provider.default.childContextTypes.skin,
    translate: _provider.default.childContextTypes.translate
  };
  constructor(props) {
    super(props);
    this.state = {
      actualPage: 0,
      maxPages: 0,
      scrollLeft: 0,
      offsetWidth: 0,
      possiblePositions: [],
      possiblePages: [],
      cardsWidth: 0
    };
    this.handleScroll_ = (0, _throttle2.default)(200, this.handleScroll.bind(this));
    this.handleScroll = this.handleScroll.bind(this);
    this.handleOnLeft = this.handleOnLeft.bind(this);
    this.handleOnRight = this.handleOnRight.bind(this);
    this.scrollTo = this.scrollTo.bind(this);
    this.updateState = (0, _debounce2.default)(200, this.updatePages.bind(this));
    this.updatePages = this.updatePages.bind(this);
    this.setCardsWrapper = this.setCardsWrapper.bind(this);
    this.getScrollWidth = this.getScrollWidth.bind(this);
    this.handleResize = this.handleResize.bind(this);

    // for testing purposes only - no other way to test this polluted component
    if (props.testingSizes) {
      const {
        offsetWidth,
        scrollLeft,
        maxPages,
        possiblePages,
        possiblePositions
      } = props.testingSizes;
      this.state.offsetWidth = offsetWidth;
      this.state.scrollLeft = scrollLeft;
      this.state.maxPages = maxPages;
      this.state.possiblePages = possiblePages;
      this.state.possiblePositions = possiblePositions;
    }
  }
  componentDidMount() {
    this.cardsWrapper.addEventListener('scroll', this.handleScroll_);
    if (window) {
      window.addEventListener('resize', this.handleResize);
    }
  }
  componentDidUpdate() {
    const {
      cards = []
    } = this.props;
    const {
      offsetWidth,
      cardsWidth
    } = this.state;
    const newCardsWidth = (0, _pipe2.default)((0, _map2.default)(computeWidth), _sum2.default)(cards);
    if (newCardsWidth !== cardsWidth && offsetWidth !== 0) {
      this.updatePaginationState(cards);
      // eslint-disable-next-line react/no-did-update-set-state
      this.setState({
        cardsWidth: newCardsWidth
      });
    }
  }
  componentWillUnmount() {
    this.cardsWrapper.removeEventListener('scroll', this.handleScroll_);
    if (window) {
      window.removeEventListener('resize', this.handleResize);
    }
    this.updateState.cancel();
  }

  /* istanbul ignore next */
  handleResize() {
    const {
      cards = []
    } = this.props;
    this.updatePaginationState(cards);
  }

  /* istanbul ignore next */
  updatePaginationState(cards) {
    const {
      offsetWidth: wrapperWidth,
      scrollLeft: wrapperScrollLeft
    } = this.state;
    const cardWidths = (0, _map2.default)(computeWidth)(cards);
    const possiblePositions = (0, _pipe2.default)((0, _reduce2.default)(([cardPositions, accWidth], cardWidth) => [[...cardPositions, accWidth], cardWidth + accWidth], [[], 0]), _head2.default)(cardWidths);
    const possiblePages = (0, _pipe2.default)((0, _reduce2.default)(([acc, pageIndex, accPageWidth], cardWidth) => {
      const pageWidth = accPageWidth + cardWidth;
      if (pageWidth > wrapperWidth) {
        return [[...acc, pageIndex + 1], pageIndex + 1, cardWidth];
      }
      return [[...acc, pageIndex], pageIndex, pageWidth];
    }, [[], 0, 0]), _head2.default)(cardWidths);
    const skip = (0, _findIndex2.default)(position => position >= wrapperScrollLeft, possiblePositions);
    const actualPage = possiblePages[skip + 1];
    this.setState({
      possiblePositions,
      possiblePages,
      maxPages: (0, _last2.default)(possiblePages),
      actualPage
    });
  }
  setCardsWrapper(element) {
    this.cardsWrapper = element;
    this.setState({
      scrollLeft: this.cardsWrapper?.scrollLeft,
      offsetWidth: this.cardsWrapper?.offsetWidth
    });
  }

  /* istanbul ignore next */
  getScrollWidth(index) {
    const {
      cards = []
    } = this.props;
    const card = cards[index];
    return computeWidth(card);
  }

  /* istanbul ignore next */
  handleScroll() {
    const scrollLeft = this.cardsWrapper?.scrollLeft;
    this.setState({
      scrollLeft
    });
    const {
      possiblePositions,
      offsetWidth
    } = this.state;
    const {
      onScroll
    } = this.props;
    if (onScroll) {
      const leftBound = scrollLeft;
      const rightBound = scrollLeft + offsetWidth;
      const leftIndex = (0, _findIndex2.default)(position => position > leftBound, possiblePositions) - 1;
      const rightIndex = (0, _findLastIndex2.default)(position => position < rightBound, possiblePositions);
      const skip = leftIndex;
      const limit = rightIndex - skip + 1;
      onScroll(skip, limit);
    }
  }
  handleOnLeft() {
    const {
      actualPage,
      maxPages
    } = this.state;
    this.scrollTo(nextPage(actualPage - 1, maxPages));
  }
  handleOnRight() {
    const {
      actualPage,
      maxPages
    } = this.state;
    this.scrollTo(nextPage(actualPage + 1, maxPages));
  }
  scrollTo(page) {
    const {
      possiblePages,
      possiblePositions
    } = this.state;
    const indexOfNextFirstCard = possiblePages.indexOf(page);
    const nextPosition = possiblePositions[indexOfNextFirstCard];
    this.cardsWrapper.scrollLeft = nextPosition;
    this.updatePages(page);
    this.setState({
      scrollLeft: nextPosition
    });
  }
  updatePages(actualPage) {
    this.setState({
      actualPage
    });
  }
  render() {
    const {
      title,
      showMore,
      cards,
      customStyle = {},
      onShowMore,
      dataName,
      contentType,
      'arrows-aria-label': ariaLabel = {},
      type
    } = this.props;
    const {
      skin
    } = this.context;
    const {
      maxPages
    } = this.state;
    const dark = (0, _getOr2.default)('#90A4AE', 'common.dark', skin);
    const titleStyle = onShowMore ? _style.default.titleLink : _style.default.title;
    const cardsView = (0, _pipe2.default)(_toPairs2.default, (0, _map2.default)(([key, card]) => {
      return /*#__PURE__*/_react.default.createElement("div", {
        className: _style.default.card,
        key: key
      }, card && type === 'learningPrioritiesCards' ? /*#__PURE__*/_react.default.createElement(_learningPriorityCard.default, _extends({}, card, {
        dataName: `${dataName}-${key}`
      })) : /*#__PURE__*/_react.default.createElement(_card.default, _extends({}, card, {
        dataName: `${dataName}-${key}`
      })));
    }))(cards);
    const arrowIconProps = {
      color: dark,
      preset: 's',
      borderRadius: '8px',
      ariaLabel: ariaLabel.showMoreOnLeftAriaLabel
    };
    const arrows = /*#__PURE__*/_react.default.createElement("div", {
      className: _style.default.arrowsWrapper
    }, /*#__PURE__*/_react.default.createElement("div", {
      className: _style.default.arrow,
      onClick: this.handleOnLeft,
      "data-name": "card-list-left-arrow"
    }, /*#__PURE__*/_react.default.createElement(_icon.default, _extends({}, arrowIconProps, {
      iconName: "arrow-left"
    }))), /*#__PURE__*/_react.default.createElement("div", {
      className: _style.default.arrow,
      onClick: this.handleOnRight,
      "data-name": "card-list-right-arrow"
    }, /*#__PURE__*/_react.default.createElement(_icon.default, _extends({}, arrowIconProps, {
      iconName: "arrow-right"
    }))));
    const titleView = typeof title === 'string' ? /*#__PURE__*/_react.default.createElement("span", {
      "data-name": "title",
      className: titleStyle,
      onClick: onShowMore
    }, /*#__PURE__*/_react.default.createElement(IconView, {
      contentType: contentType
    }), /*#__PURE__*/_react.default.createElement("span", null, title)) : /*#__PURE__*/_react.default.createElement("span", {
      className: _style.default.titleNode
    }, title);
    const hasPages = maxPages > 0;
    const showMoreView = hasPages && showMore && onShowMore ? /*#__PURE__*/_react.default.createElement(ShowMoreLink, {
      className: hasPages ? _style.default.showMoreBar : _style.default.showMore,
      onShowMore: onShowMore,
      showMore: showMore
    }) : null;
    const switchPagesView = hasPages ? /*#__PURE__*/_react.default.createElement("div", {
      className: _style.default.pagingWrapper
    }, showMoreView, arrows) : null;
    return /*#__PURE__*/_react.default.createElement("div", {
      className: _style.default.wrapper,
      style: customStyle,
      "data-name": "cardsList",
      "data-max-pages": `${maxPages}`
      // eslint-disable-next-line react/destructuring-assignment
      ,
      "data-actual-page": `${this.state.actualPage}`,
      "data-scroll-left": this.cardsWrapper?.scrollLeft
    }, /*#__PURE__*/_react.default.createElement("div", {
      className: _style.default.list
    }, /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("div", {
      "data-name": "header",
      className: _style.default.header
    }, titleView, switchPagesView), /*#__PURE__*/_react.default.createElement("div", {
      className: _style.default.cards,
      "data-testid": "cards-view-wrapper",
      ref: this.setCardsWrapper
    }, cardsView))));
  }
}
CardsList.propTypes = process.env.NODE_ENV !== "production" ? {
  contentType: _propTypes.default.string,
  dataName: _propTypes.default.string,
  title: _propTypes.default.oneOfType([_propTypes.default.node, _propTypes.default.string]),
  showMore: _propTypes.default.string,
  cards: _propTypes.default.arrayOf(_propTypes.default.oneOfType([_propTypes.default.shape(_card.cardPropTypes), _propTypes.default.shape(_learningPriorityCard.default.propTypes)])),
  customStyle: _propTypes.default.objectOf(_propTypes.default.string),
  onScroll: _propTypes.default.func,
  onShowMore: _propTypes.default.func,
  'arrows-aria-label': _propTypes.default.shape({
    showMoreOnLeftAriaLabel: _propTypes.default.string,
    showMoreOnRightAriaLabel: _propTypes.default.string
  }),
  type: _propTypes.default.oneOf(['cards', 'learningPrioritiesCards']),
  // eslint-disable-next-line react/forbid-prop-types
  testingSizes: _propTypes.default.any
} : {};
var _default = exports.default = CardsList;
//# sourceMappingURL=index.js.map