'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.focusRegistry = undefined;
exports.updateMouseFromRI = updateMouseFromRI;

var _notifier = require('./notifier');

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

// the shape of what's being tracked globally
// the input object is the default export
var input = {
  mouse: {
    mouseOnDocument: false,
    clientX: 0,
    clientY: 0,
    buttons: 0
  },
  touch: {
    touchOnScreen: false,
    recentTouch: false
  },
  key: {
    recentEnterKeyDown: false
  }
};

// update touch input tracking
var touchTimerID = null;
function updateTouch(e) {
  if (e.type === 'touchstart') {
    input.touch.touchOnScreen = true;
    input.mouse.mouseOnDocument = false;
  } else if (e.type === 'touchend' || e.type === 'touchcancel') {
    input.touch.recentTouch = true;
    if (touchTimerID) window.clearTimeout(touchTimerID);
    touchTimerID = window.setTimeout(function () {
      input.touch.recentTouch = false;
      touchTimerID = null;
    }, _constants.queueTime);
  }

  if (e.touches.length === 0) {
    input.touch.touchOnScreen = false;
  }
}

// update mouse input tracking
function updateMouse(e) {
  input.mouse.clientX = e.clientX;
  input.mouse.clientY = e.clientY;
  input.mouse.buttons = e.buttons;
  if (e.type === 'mouseleave') input.mouse.mouseOnDocument = false;else input.mouse.mouseOnDocument = true;
}

// only update mouse if the mouse event is not from a touch event
function updateHybridMouse(e) {
  if (input.touch.recentTouch || input.touch.touchOnScreen) return;
  updateMouse(e);
}

// update recent enter keydown tracking, used for form submission detection
var enterKeyDownTimerID = null;
function updateEnterKeyDown(e) {
  if (e.key === 'Enter') {
    input.key.recentEnterKeyDown = true;
    if (enterKeyDownTimerID) window.clearTimeout(enterKeyDownTimerID);
    enterKeyDownTimerID = window.setTimeout(function () {
      input.key.recentEnterKeyDown = false;
      enterKeyDownTimerID = null;
    }, _constants.queueTime);
  }
}

// update mouse from RI - this is required for enter and leave events from RI elements
// because when the mouse is moved onto an RI element the most recent mousemove event
// will have the mouse coordinates as off the element, so need to get updated coordinates
// from the react event
function updateMouseFromRI(e) {
  updateMouse(e);
  input.mouse.mouseOnDocument = true;
}

// sign up for notification of touch events if the device supports the touch events api
if (_constants.deviceHasTouch) {
  (0, _notifier.notifyOfAll)(Object.keys(_constants.touchEvents), updateTouch);
}

// sign up for notification of mouse events if the device has a mouse
if (_constants.deviceHasMouse) {
  (0, _notifier.notifyOfAll)(Object.keys(_constants.mouseEvents), _constants.deviceType === 'hybrid' ? updateHybridMouse : updateMouse);
}

// sign up for notification of enter keydown events for form submission detection
(0, _notifier.notifyOfAll)(['keydown'], updateEnterKeyDown);

// focus registry used by RI to track events that cause focus/blur calls (e.g. mousedown)
// so focus/blur is not called twice as event bubbles through nested RIs
var focusRegistry = exports.focusRegistry = {
  focus: null,
  blur: null
};

exports.default = input;