/* eslint-disable no-restricted-globals */
/**
 * Utility method to apply ripple effect for the given event by:
 * 1. create a mask element,
 * 2. add it to the target element,
 * 3. and add a ripple element to the mask
 *
 * @param {MouseEvent} e - The event object that was triggered.
 */
export const triggerRipple = (e) => {
  const target = e.currentTarget;
  const mask = document.createElement('div');
  mask.classList.add('v-animation-ripple-mask');
  const computer_style = window.getComputedStyle(target);
  mask.style.borderRadius = computer_style.borderRadius;
  // Needed for Firefox
  mask.style['-webkit-border-bottom-left-radius'] = computer_style['-webkit-border-bottom-left-radius'];
  mask.style['-webkit-border-bottom-right-radius'] = computer_style['-webkit-border-bottom-right-radius'];
  mask.style['-webkit-border-top-left-radius'] = computer_style['-webkit-border-top-left-radius'];
  mask.style['-webkit-border-top-right-radius'] = computer_style['-webkit-border-top-right-radius'];
  const circle = document.createElement('span');
  const diameter = Math.max(target.clientWidth, target.clientHeight);
  const radius = diameter / 2;
  const rect = target.getBoundingClientRect();
  circle.style.width = circle.style.height = `${diameter}px`;
  circle.style.left = `${e.clientX - (rect.x + radius)}px`;
  circle.style.top = `${e.clientY - (rect.y + radius)}px`;
  circle.classList.add('v-animation-ripple');
  const ripple = target.getElementsByClassName('v-animation-ripple-mask')[0];
  if (ripple) {
    ripple.remove();
  }
  target.classList.add('v-animation-ripple-container');
  target.appendChild(mask);
  mask.appendChild(circle);
};
/* eslint-enable no-restricted-globals */
/**
 * Takes an element and returns its offsetHeight to trigger reflow,
 * which can be used to reset the animation.
 * For more details, {@see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation}
 *
 * Note: we cannot simply invoke `element.offsetHeight` to trigger reflow
 *       as the statement will get erased during VM optimization phase
 *
 * @param {HTMLElement} element - HTMLElement - The element to be measured.
 * return the offsetHeight of the given element
 */
export const reflow = (element) => {
  const offsetHeight = element.offsetHeight;
  if (!isNaN(offsetHeight)) {
    element.dataset['vegaReflow'] = offsetHeight.toString();
  }
};
/**
 * Executes a callback after a transition has ended on a given element
 *
 * @param {() => void} callback - The function to execute after the transition ends
 * @param {HTMLElement} element - The element to listen for transitionend event on
 * @param {number} [timeout] - The timeout in milliseconds after which the callback will be executed even if the
 * transitionend event hasn't been fired.
 */
export function executeAfterTransition(callback, element, timeout) {
  // timeoutId cannot be number since typescript/jest is taking it as NodeJS.Timeout instead of window.setTimeout
  let timeoutId = 0;
  /**
   * The handler used to listen for transitionend event
   */
  const handler = () => {
    element.removeEventListener('transitionend', handler);
    timeout && clearTimeout(timeoutId);
    callback();
  };
  element.addEventListener('transitionend', handler);
  timeoutId = timeout ? setTimeout(handler, timeout) : 0;
}
