"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.getPointFromPointerEvent = exports.createPositionChangeChecker = exports.createPointerHitListener = exports.createPointerEventListener = void 0;
/**
 * @param {MouseEvent|TouchEvent} evt
 * @param {HTMLElement} relativeTo
 * @returns {{x: number, y: number}}
 */
var getPointFromPointerEvent = exports.getPointFromPointerEvent = function getPointFromPointerEvent(evt, relativeTo) {
  var x, y;
  var touches = evt.changedTouches && evt.changedTouches.length > 0 && evt.changedTouches || evt.touches;
  if (touches && touches.length > 0) {
    x = touches[0].clientX;
    y = touches[0].clientY;
  } else {
    x = evt.clientX;
    y = evt.clientY;
  }
  if (relativeTo) {
    var _relativeTo$getBoundi = relativeTo.getBoundingClientRect(),
      top = _relativeTo$getBoundi.top,
      left = _relativeTo$getBoundi.left;
    x -= left;
    y -= top;
  }
  return {
    x: x,
    y: y
  };
};

/**
 * Creates and stores the print of the event position for later comparison.
 * It can be used to create a position change checker function, in order to solve the problem
 * of Chrome's automatically triggered mousemove event when clicking without moving the mouse.
 * @param evt
 * @returns {function(*=): boolean}
 */
var createPositionChangeChecker = exports.createPositionChangeChecker = function createPositionChangeChecker(evt) {
  var getPositionPrint = function getPositionPrint(evt) {
    return '' + evt.pageX + '-' + evt.pageY;
  };
  var initialPrint = getPositionPrint(evt);
  return function (evt) {
    return initialPrint !== getPositionPrint(evt);
  };
};

/**
 * Creates a "hit" event listener.
 * It detects a single tap (or click) - if the pointer was released without moving.
 * @param element
 * @param {function} fn The event handler function
 * @returns {function()} A function to be called to remove the event listeners
 */
var createPointerHitListener = exports.createPointerHitListener = function createPointerHitListener(element, fn) {
  var moved = false;
  var checkPositionChange = false;

  // preventing the emulated mouse events after touchend
  // see https://developer.mozilla.org/en-US/docs/Web/API/Touch_events/Supporting_both_TouchEvent_and_MouseEvent
  var preventEmulatedEvents = function preventEmulatedEvents(cb) {
    return function (evt) {
      if (!moved && evt.type === 'touchend') {
        evt.preventDefault();
      }
      cb(evt);
    };
  };
  var startHandler = function startHandler(evt) {
    moved = false;
    var isTouch = (evt.changedTouches || evt.touches || []).length > 0;
    if (isTouch) {
      // in case of touch events we can skip the check, the events are fired correctly
      checkPositionChange = false;
      element.addEventListener('touchmove', moveHandler, true);
      element.addEventListener('touchend', endHandler);
    } else {
      checkPositionChange = createPositionChangeChecker(evt);
      element.addEventListener('mousemove', moveHandler);
      element.addEventListener('mouseup', endHandler);
    }
  };
  var moveHandler = function moveHandler(evt) {
    if (checkPositionChange) {
      moved = checkPositionChange(evt);
    } else {
      moved = true;
    }
  };
  var endHandler = preventEmulatedEvents(function () {
    !moved && fn.apply(void 0, arguments);
    element.removeEventListener('touchmove', moveHandler, true);
    element.removeEventListener('mousemove', moveHandler);
    element.removeEventListener('touchend', endHandler);
    element.removeEventListener('mouseup', endHandler);
  });
  element.addEventListener('mousedown', startHandler);
  element.addEventListener('touchstart', startHandler);
  return function () {
    element.removeEventListener('mousedown', startHandler);
    element.removeEventListener('touchstart', startHandler);
  };
};

/**
 * Creates a general pointer event listener (for mouse and touch events)
 * @param element
 * @param {string} name The name of the event phase ('start'|'move'|'end')
 * @param {function} fn The event handler function
 * @returns {function()} A function to be called to remove the event listeners
 */
var createPointerEventListener = exports.createPointerEventListener = function createPointerEventListener(element, name, fn) {
  var touchName, mouseName;
  switch (name) {
    case 'start':
      {
        touchName = 'touchstart';
        mouseName = 'mousedown';
        break;
      }
    case 'move':
      {
        touchName = 'touchmove';
        mouseName = 'mousemove';
        break;
      }
    case 'end':
      {
        touchName = 'touchend';
        mouseName = 'mouseup';
        break;
      }
  }
  var tolerance = 1; // ms
  var timeStamp = 0;
  var touchHandler = function touchHandler(evt) {
    // prevent mouse events if it's a touch event
    //evt.type.indexOf('touch') === 0 && evt.preventDefault();
    timeStamp = evt.timeStamp;
    for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
      args[_key - 1] = arguments[_key];
    }
    fn.apply(void 0, [evt].concat(args));
  };
  var mouseHandler = function mouseHandler(evt) {
    if (evt.timeStamp - timeStamp < tolerance) {
      // eslint-disable-next-line no-console
      console.log('Skipped double event handling.');
      return;
    }
    for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
      args[_key2 - 1] = arguments[_key2];
    }
    fn.apply(void 0, [evt].concat(args));
  };
  element.addEventListener(touchName, touchHandler);
  element.addEventListener(mouseName, mouseHandler);
  return function () {
    element.removeEventListener(touchName, touchHandler);
    element.removeEventListener(mouseName, mouseHandler);
  };
};