'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _index = require('../index.js');

var _index2 = _interopRequireDefault(_index);

var _functions = require('../functions.js');

var _functions2 = _interopRequireDefault(_functions);

var _mapbrowsereventtype = require('../mapbrowsereventtype.js');

var _mapbrowsereventtype2 = _interopRequireDefault(_mapbrowsereventtype);

var _mapbrowserpointerevent = require('../mapbrowserpointerevent.js');

var _mapbrowserpointerevent2 = _interopRequireDefault(_mapbrowserpointerevent);

var _interaction = require('../interaction/interaction.js');

var _interaction2 = _interopRequireDefault(_interaction);

var _obj = require('../obj.js');

var _obj2 = _interopRequireDefault(_obj);

function _interopRequireDefault(obj) {
  return obj && obj.__esModule ? obj : { default: obj };
}

/**
 * @classdesc
 * Base class that calls user-defined functions on `down`, `move` and `up`
 * events. This class also manages "drag sequences".
 *
 * When the `handleDownEvent` user function returns `true` a drag sequence is
 * started. During a drag sequence the `handleDragEvent` user function is
 * called on `move` events. The drag sequence ends when the `handleUpEvent`
 * user function is called and returns `false`.
 *
 * @constructor
 * @param {olx.interaction.PointerOptions=} opt_options Options.
 * @extends {ol.interaction.Interaction}
 * @api
 */
var _ol_interaction_Pointer_ = function (opt_options) {

  var options = opt_options ? opt_options : {};

  var handleEvent = options.handleEvent ? options.handleEvent : _ol_interaction_Pointer_.handleEvent;

  _interaction2.default.call(this, {
    handleEvent: handleEvent
  });

  /**
   * @type {function(ol.MapBrowserPointerEvent):boolean}
   * @private
   */
  this.handleDownEvent_ = options.handleDownEvent ? options.handleDownEvent : _ol_interaction_Pointer_.handleDownEvent;

  /**
   * @type {function(ol.MapBrowserPointerEvent)}
   * @private
   */
  this.handleDragEvent_ = options.handleDragEvent ? options.handleDragEvent : _ol_interaction_Pointer_.handleDragEvent;

  /**
   * @type {function(ol.MapBrowserPointerEvent)}
   * @private
   */
  this.handleMoveEvent_ = options.handleMoveEvent ? options.handleMoveEvent : _ol_interaction_Pointer_.handleMoveEvent;

  /**
   * @type {function(ol.MapBrowserPointerEvent):boolean}
   * @private
   */
  this.handleUpEvent_ = options.handleUpEvent ? options.handleUpEvent : _ol_interaction_Pointer_.handleUpEvent;

  /**
   * @type {boolean}
   * @protected
   */
  this.handlingDownUpSequence = false;

  /**
   * @type {Object.<string, ol.pointer.PointerEvent>}
   * @private
   */
  this.trackedPointers_ = {};

  /**
   * @type {Array.<ol.pointer.PointerEvent>}
   * @protected
   */
  this.targetPointers = [];
};

_index2.default.inherits(_ol_interaction_Pointer_, _interaction2.default);

/**
 * @param {Array.<ol.pointer.PointerEvent>} pointerEvents List of events.
 * @return {ol.Pixel} Centroid pixel.
 */
_ol_interaction_Pointer_.centroid = function (pointerEvents) {
  var length = pointerEvents.length;
  var clientX = 0;
  var clientY = 0;
  for (var i = 0; i < length; i++) {
    clientX += pointerEvents[i].clientX;
    clientY += pointerEvents[i].clientY;
  }
  return [clientX / length, clientY / length];
};

/**
 * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
 * @return {boolean} Whether the event is a pointerdown, pointerdrag
 *     or pointerup event.
 * @private
 */
_ol_interaction_Pointer_.prototype.isPointerDraggingEvent_ = function (mapBrowserEvent) {
  var type = mapBrowserEvent.type;
  return type === _mapbrowsereventtype2.default.POINTERDOWN || type === _mapbrowsereventtype2.default.POINTERDRAG || type === _mapbrowsereventtype2.default.POINTERUP;
};

/**
 * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
 * @private
 */
_ol_interaction_Pointer_.prototype.updateTrackedPointers_ = function (mapBrowserEvent) {
  if (this.isPointerDraggingEvent_(mapBrowserEvent)) {
    var event = mapBrowserEvent.pointerEvent;

    var id = event.pointerId.toString();
    if (mapBrowserEvent.type == _mapbrowsereventtype2.default.POINTERUP) {
      delete this.trackedPointers_[id];
    } else if (mapBrowserEvent.type == _mapbrowsereventtype2.default.POINTERDOWN) {
      this.trackedPointers_[id] = event;
    } else if (id in this.trackedPointers_) {
      // update only when there was a pointerdown event for this pointer
      this.trackedPointers_[id] = event;
    }
    this.targetPointers = _obj2.default.getValues(this.trackedPointers_);
  }
};

/**
 * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
 * @this {ol.interaction.Pointer}
 */
_ol_interaction_Pointer_.handleDragEvent = _index2.default.nullFunction;

/**
 * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
 * @return {boolean} Capture dragging.
 * @this {ol.interaction.Pointer}
 */
_ol_interaction_Pointer_.handleUpEvent = _functions2.default.FALSE;

/**
 * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
 * @return {boolean} Capture dragging.
 * @this {ol.interaction.Pointer}
 */
_ol_interaction_Pointer_.handleDownEvent = _functions2.default.FALSE;

/**
 * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
 * @this {ol.interaction.Pointer}
 */
_ol_interaction_Pointer_.handleMoveEvent = _index2.default.nullFunction;

/**
 * Handles the {@link ol.MapBrowserEvent map browser event} and may call into
 * other functions, if event sequences like e.g. 'drag' or 'down-up' etc. are
 * detected.
 * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
 * @return {boolean} `false` to stop event propagation.
 * @this {ol.interaction.Pointer}
 * @api
 */
_ol_interaction_Pointer_.handleEvent = function (mapBrowserEvent) {
  if (!(mapBrowserEvent instanceof _mapbrowserpointerevent2.default)) {
    return true;
  }

  var stopEvent = false;
  this.updateTrackedPointers_(mapBrowserEvent);
  if (this.handlingDownUpSequence) {
    if (mapBrowserEvent.type == _mapbrowsereventtype2.default.POINTERDRAG) {
      this.handleDragEvent_(mapBrowserEvent);
    } else if (mapBrowserEvent.type == _mapbrowsereventtype2.default.POINTERUP) {
      var handledUp = this.handleUpEvent_(mapBrowserEvent);
      this.handlingDownUpSequence = handledUp && this.targetPointers.length > 0;
    }
  } else {
    if (mapBrowserEvent.type == _mapbrowsereventtype2.default.POINTERDOWN) {
      var handled = this.handleDownEvent_(mapBrowserEvent);
      this.handlingDownUpSequence = handled;
      stopEvent = this.shouldStopEvent(handled);
    } else if (mapBrowserEvent.type == _mapbrowsereventtype2.default.POINTERMOVE) {
      this.handleMoveEvent_(mapBrowserEvent);
    }
  }
  return !stopEvent;
};

/**
 * This method is used to determine if "down" events should be propagated to
 * other interactions or should be stopped.
 *
 * The method receives the return code of the "handleDownEvent" function.
 *
 * By default this function is the "identity" function. It's overidden in
 * child classes.
 *
 * @param {boolean} handled Was the event handled by the interaction?
 * @return {boolean} Should the event be stopped?
 * @protected
 */
_ol_interaction_Pointer_.prototype.shouldStopEvent = function (handled) {
  return handled;
};
exports.default = _ol_interaction_Pointer_;
module.exports = exports['default'];