"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _utils = require("../../utils");

var _react = _interopRequireWildcard(require("react"));

var _propTypes = _interopRequireDefault(require("prop-types"));

var _classnames = _interopRequireDefault(require("classnames"));

var _reactMeasure = _interopRequireDefault(require("react-measure"));

var _constants = require("../../constants");

var _Icon = _interopRequireDefault(require("../Icon"));

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

// Copyright 1999-2020. Plesk International GmbH. All rights reserved.
const calcWidths = node => {
  const slideWidths = [].map.call(node.childNodes, el => el.clientWidth);
  const totalWidth = slideWidths.reduce((prev, curr) => prev + curr, 0);
  return {
    slideWidths,
    totalWidth
  };
};
/**
 * Carousel component is used for optimizing page space by displaying only some parts
 * of entire content in a cyclic view.
 * @since 0.0.42
 */


class Carousel extends _react.Component {
  constructor(props) {
    super(props);
    (0, _defineProperty2.default)(this, "state", {
      showControls: false,
      current: 0,
      next: 0,
      moving: false,
      slideWidths: [],
      totalWidth: 0
    });
    this.speed = 500;
    this.movingCallback = null;
    this.playSpeed = 5000;
    this.playTimer = null;
    this.handlePrevClick = this.handlePrevClick.bind(this);
    this.handleNextClick = this.handleNextClick.bind(this);
    this.stop = this.stop.bind(this);
    this.play = this.play.bind(this);
    this.handleResize = this.handleResize.bind(this);
    this.rootRef = /*#__PURE__*/(0, _react.createRef)();
    this.genuineRef = /*#__PURE__*/(0, _react.createRef)();
  }

  componentDidMount() {
    this.isRtl = (0, _utils.isRtl)();
    this.play();
  }

  componentDidUpdate() {
    const {
      width
    } = this.rootRef.current.getBoundingClientRect();
    const {
      slideWidths,
      totalWidth
    } = calcWidths(this.genuineRef.current);

    if (this.state.totalWidth !== totalWidth) {
      // eslint-disable-next-line react/no-did-update-set-state
      this.setState({
        slideWidths,
        totalWidth,
        showControls: width < totalWidth
      });
    }
  }

  componentWillUnmount() {
    this.stop();
    clearTimeout(this.movingCallback);
  }

  handlePrevClick() {
    this.stop();
    this.setCurrentSlide(this.state.current - 1);
  }

  handleNextClick() {
    this.stop();
    this.setCurrentSlide(this.state.current + 1);
  }

  play() {
    this.playTimer = setTimeout(() => {
      this.setCurrentSlide(this.state.current + 1);
      this.play();
    }, this.playSpeed);
  }

  stop() {
    if (this.playTimer) {
      clearTimeout(this.playTimer);
      this.playTimer = null;
    }
  }

  setCurrentSlide(next) {
    const {
      slideWidths,
      moving
    } = this.state;

    if (moving) {
      return;
    }

    let current = next;

    if (current < 0) {
      current = slideWidths.length - 1;
    }

    if (current >= slideWidths.length) {
      current = 0;
    }

    this.setState({
      current,
      next,
      moving: true
    });
    this.movingCallback = setTimeout(() => {
      this.movingCallback = null;
      this.setState({
        moving: false
      });
    }, this.speed);
  }

  handleResize({
    bounds: {
      width
    }
  }) {
    const node = this.genuineRef.current;
    const {
      slideWidths,
      totalWidth
    } = calcWidths(node);
    this.setState({
      slideWidths,
      totalWidth,
      showControls: width < totalWidth
    });
  }

  listStyle() {
    const {
      current,
      next,
      moving,
      slideWidths,
      totalWidth
    } = this.state;
    const moveTo = moving ? next : current;
    let x = -totalWidth + 26;

    if (moveTo < 0) {
      for (let i = moveTo; i < 0; i++) {
        x += slideWidths[i + slideWidths.length];
      }
    } else {
      for (let i = 0; i < moveTo; i++) {
        x -= slideWidths[i % slideWidths.length];
      }
    }

    if (this.isRtl) {
      x = -x;
    }

    return {
      WebkitTransform: `translateX(${x ? `${x}px` : 0})`,
      transform: `translateX(${x ? `${x}px` : 0})`,
      WebkitTransition: moving ? `-webkit-transform ${this.speed}ms ease` : null,
      transition: moving ? `transform ${this.speed}ms ease` : null
    };
  }

  render() {
    const {
      showControls
    } = this.state;
    const {
      baseClassName,
      className,
      children,
      ...props
    } = this.props;
    return /*#__PURE__*/_react.default.createElement(_reactMeasure.default, {
      onResize: this.handleResize,
      bounds: true,
      innerRef: node => {
        this.rootRef.current = node;
      }
    }, ({
      measureRef
    }) => /*#__PURE__*/_react.default.createElement("section", (0, _extends2.default)({
      ref: measureRef,
      className: (0, _classnames.default)(baseClassName, className)
    }, props), /*#__PURE__*/_react.default.createElement("div", {
      className: `${baseClassName}__slides`,
      style: showControls ? this.listStyle() : null
    }, showControls && children, /*#__PURE__*/_react.default.createElement("div", {
      className: `${baseClassName}__genuine-slides`,
      ref: this.genuineRef
    }, children), showControls && children), showControls && /*#__PURE__*/_react.default.createElement("div", {
      className: `${baseClassName}__controls`
    }, /*#__PURE__*/_react.default.createElement("button", {
      type: "button",
      className: (0, _classnames.default)(`${baseClassName}__control`, `${baseClassName}__control--previous`),
      onClick: this.handlePrevClick
    }, /*#__PURE__*/_react.default.createElement(_Icon.default, {
      name: "chevron-left",
      flipHorizontal: this.isRtl,
      className: `${baseClassName}__control-icon`
    })), /*#__PURE__*/_react.default.createElement("button", {
      type: "button",
      className: (0, _classnames.default)(`${baseClassName}__control`, `${baseClassName}__control--next`),
      onClick: this.handleNextClick
    }, /*#__PURE__*/_react.default.createElement(_Icon.default, {
      name: "chevron-right",
      flipHorizontal: this.isRtl,
      className: `${baseClassName}__control-icon`
    })))));
  }

}

Carousel.propTypes = {
  /**
   * Slides
   * @since 0.0.42
   */
  children: _propTypes.default.node,

  /**
   * @ignore
   */
  className: _propTypes.default.string,

  /**
   * @ignore
   */
  baseClassName: _propTypes.default.string
};
Carousel.defaultProps = {
  children: null,
  className: null,
  baseClassName: `${_constants.CLS_PREFIX}carousel`
};
var _default = Carousel;
exports.default = _default;