/**
 * @file
 * Animated number
 */

(($, Drupal, once) => {
  /**
   * Add function to Number prototype to format a number of String type
   * @param {number} n The value of the current step
   * @return {String} Returns formatted string with spaces separating the place value
   */
  function formatNumber(n) {
    const number = Number(n);
    const r = /\B(?=(\d{3})+(?!\d))/g;
    return number.toFixed().replace(r, '$& ');
  }

  function countUp(elem) {
    let current = 0;
    const duration = Math.ceil(+elem.getAttribute('data-duration') * 1000);
    const max = elem.getAttribute('data-number');

    // No animation.
    if (duration === 0) {
      elem.innerHTML = formatNumber(max);
      return;
    }

    const animationInterval = 10;
    const numberOfSteps = duration / animationInterval;
    const step = max / numberOfSteps;

    // eslint-disable-next-line no-use-before-define
    const interval = setInterval(increase, animationInterval);

    function increase() {
      current += step;
      if (current >= max) {
        elem.innerHTML = formatNumber(max);
        clearInterval(interval);
      } else {
        elem.innerHTML = formatNumber(current);
      }
    }
  }

  /**
   * Attach an animation behavior to each number block.
   *
   * @type {Drupal~behavior}
   */
  Drupal.behaviors.animate_number = {
    attach() {
      const $number = $(once('animated-number', '.js-animated-number'));
      const observerOptions = {
        threshold: 0.3,
      };
      // Set observer which will trigger an action when the element is
      // in view.
      const observer = new IntersectionObserver((intersections) => {
        intersections.forEach(({ target, isIntersecting }) => {
          // If target is within view.
          if (isIntersecting) {
            countUp(target);
            // When action is finished, stop observing target.
            observer.unobserve(target);
          }
        });
      }, observerOptions);
      // For each number, add an observer.
      // The observer requires an HTML element, not a jQuery object.
      $number.each(function getNumbers() {
        observer.observe($(this)[0]);
      });
    },
  };
})(jQuery, Drupal, once);
