/**
 * Wait until an element has stopped scrolling
 * This considers the element to have stopped scrolling, as soon as it did not change its
 * scroll position for 20 successive animation frames
 * @param {HTMLElement} element - The element which is scrolled
 * @param {numeric} timeoutInMs - A timeout in ms. If the timeout has elapsed, the promise rejects
 * @returns A promise which resolves after the scrolling has stopped
 */
export const waitForScrollingToEnd = (element: Element, timeoutInMs = 500): Promise<void> => {
  let lastLeft = element.scrollLeft;
  let lastTop = element.scrollTop;
  let framesWithoutChange = 0;

  return new Promise((resolve, reject) => {
    const timeout = window.setTimeout(() => {
      reject(new Error('Waiting for scroll end timed out'));
    }, timeoutInMs);

    function checkScrollingChanged() {
      if (element.scrollLeft !== lastLeft || element.scrollTop !== lastTop) {
        framesWithoutChange = 0;
        lastLeft = window.scrollX;
        lastTop = window.scrollY;
      } else {
        framesWithoutChange++;
        if (framesWithoutChange >= 20) {
          clearTimeout(timeout);
          resolve();
        }
      }
      window.requestAnimationFrame(checkScrollingChanged);
    }

    checkScrollingChanged();
  });
};
