text: /**
   * @module ol/interaction/DragBox
   */
  // FIXME draw drag box
  import Event from '../events/Event.js';
  import {always, mouseOnly, mouseActionButton} from '../events/condition.js';
  import {VOID} from '../functions.js';
  import PointerInteraction from '../interaction/Pointer.js';
  import RenderBox from '../render/Box.js';
  
  
  /**
   * A function that takes a {@link module:ol/MapBrowserEvent} and two
   * {@link module:ol/pixel~Pixel}s and returns a `{boolean}`. If the condition is met,
   * true should be returned.
   * @typedef {function(this: ?, import("../MapBrowserEvent.js").default, import("../pixel.js").Pixel, import("../pixel.js").Pixel):boolean} EndCondition
   */
  
  
  /**
   * @typedef {Object} Options
   * @property {string} [className='ol-dragbox'] CSS class name for styling the box.
   * @property {import("../events/condition.js").Condition} [condition] A function that takes an {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a boolean
   * to indicate whether that event should be handled.
   * Default is {@link ol/events/condition~always}.
   * @property {number} [minArea=64] The minimum area of the box in pixel, this value is used by the default
   * `boxEndCondition` function.
   * @property {EndCondition} [boxEndCondition] A function that takes a {@link module:ol/MapBrowserEvent~MapBrowserEvent} and two
   * {@link module:ol/pixel~Pixel}s to indicate whether a `boxend` event should be fired.
   * Default is `true` if the area of the box is bigger than the `minArea` option.
   * @property {function(this:DragBox, import("../MapBrowserEvent.js").default)} onBoxEnd Code to execute just
   * before `boxend` is fired.
   */
  
  
  /**
   * @enum {string}
   */
  const DragBoxEventType = {
    /**
     * Triggered upon drag box start.
     * @event DragBoxEvent#boxstart
     * @api
     */
    BOXSTART: 'boxstart',
  
    /**
     * Triggered on drag when box is active.
     * @event DragBoxEvent#boxdrag
     * @api
     */
    BOXDRAG: 'boxdrag',
  
    /**
     * Triggered upon drag box end.
     * @event DragBoxEvent#boxend
     * @api
     */
    BOXEND: 'boxend'
  };
  
  
  /**
   * @classdesc
   * Events emitted by {@link module:ol/interaction/DragBox~DragBox} instances are instances of
   * this type.
   */
  class DragBoxEvent extends Event {
  
    /**
     * @param {string} type The event type.
     * @param {import("../coordinate.js").Coordinate} coordinate The event coordinate.
     * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Originating event.
     */
    constructor(type, coordinate, mapBrowserEvent) {
      super(type);
  
      /**
       * The coordinate of the drag event.
       * @const
       * @type {import("../coordinate.js").Coordinate}
       * @api
       */
      this.coordinate = coordinate;
  
      /**
       * @const
       * @type {import("../MapBrowserEvent.js").default}
       * @api
       */
      this.mapBrowserEvent = mapBrowserEvent;
  
    }
  
  }
  
  
  /**
   * @classdesc
   * Allows the user to draw a vector box by clicking and dragging on the map,
   * normally combined with an {@link module:ol/events/condition} that limits
   * it to when the shift or other key is held down. This is used, for example,
   * for zooming to a specific area of the map
   * (see {@link module:ol/interaction/DragZoom~DragZoom} and
   * {@link module:ol/interaction/DragRotateAndZoom}).
   *
   * This interaction is only supported for mouse devices.
   *
   * @fires DragBoxEvent
   * @api
   */
  class DragBox extends PointerInteraction {
    /**
     * @param {Options=} opt_options Options.
     */
    constructor(opt_options) {
  
      super({
        handleDownEvent: handleDownEvent,
        handleDragEvent: handleDragEvent,
        handleUpEvent: handleUpEvent
      });
  
      const options = opt_options ? opt_options : {};
  
      /**
      * @type {import("../render/Box.js").default}
      * @private
      */
      this.box_ = new RenderBox(options.className || 'ol-dragbox');
  
      /**
      * @type {number}
      * @private
      */
      this.minArea_ = options.minArea !== undefined ? options.minArea : 64;
  
      /**
       * Function to execute just before `onboxend` is fired
       * @type {function(this:DragBox, import("../MapBrowserEvent.js").default)}
       * @private
       */
      this.onBoxEnd_ = options.onBoxEnd ? options.onBoxEnd : VOID;
  
      /**
      * @type {import("../pixel.js").Pixel}
      * @private
      */
      this.startPixel_ = null;
  
      /**
      * @private
      * @type {import("../events/condition.js").Condition}
      */
      this.condition_ = options.condition ? options.condition : always;
  
      /**
      * @private
      * @type {EndCondition}
      */
      this.boxEndCondition_ = options.boxEndCondition ?
        options.boxEndCondition : defaultBoxEndCondition;
    }
  
    /**
    * Returns geometry of last drawn box.
    * @return {import("../geom/Polygon.js").default} Geometry.
    * @api
    */
    getGeometry() {
      return this.box_.getGeometry();
    }
  }
  
  
  /**
   * The default condition for determining whether the boxend event
   * should fire.
   * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent The originating MapBrowserEvent
   *     leading to the box end.
   * @param {import("../pixel.js").Pixel} startPixel The starting pixel of the box.
   * @param {import("../pixel.js").Pixel} endPixel The end pixel of the box.
   * @return {boolean} Whether or not the boxend condition should be fired.
   * @this {DragBox}
   */
  function defaultBoxEndCondition(mapBrowserEvent, startPixel, endPixel) {
    const width = endPixel[0] - startPixel[0];
    const height = endPixel[1] - startPixel[1];
    return width * width + height * height >= this.minArea_;
  }
  
  
  /**
   * @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
   * @this {DragBox}
   */
  function handleDragEvent(mapBrowserEvent) {
    if (!mouseOnly(mapBrowserEvent)) {
      return;
    }
  
    this.box_.setPixels(this.startPixel_, mapBrowserEvent.pixel);
  
    this.dispatchEvent(new DragBoxEvent(DragBoxEventType.BOXDRAG,
      mapBrowserEvent.coordinate, mapBrowserEvent));
  }
  
  
  /**
   * @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
   * @return {boolean} Stop drag sequence?
   * @this {DragBox}
   */
  function handleUpEvent(mapBrowserEvent) {
    if (!mouseOnly(mapBrowserEvent)) {
      return true;
    }
  
    this.box_.setMap(null);
  
    if (this.boxEndCondition_(mapBrowserEvent, this.startPixel_, mapBrowserEvent.pixel)) {
      this.onBoxEnd_(mapBrowserEvent);
      this.dispatchEvent(new DragBoxEvent(DragBoxEventType.BOXEND,
        mapBrowserEvent.coordinate, mapBrowserEvent));
    }
    return false;
  }
  
  
  /**
   * @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
   * @return {boolean} Start drag sequence?
   * @this {DragBox}
   */
  function handleDownEvent(mapBrowserEvent) {
    if (!mouseOnly(mapBrowserEvent)) {
      return false;
    }
  
    if (mouseActionButton(mapBrowserEvent) &&
        this.condition_(mapBrowserEvent)) {
      this.startPixel_ = mapBrowserEvent.pixel;
      this.box_.setMap(mapBrowserEvent.map);
      this.box_.setPixels(this.startPixel_, this.startPixel_);
      this.dispatchEvent(new DragBoxEvent(DragBoxEventType.BOXSTART,
        mapBrowserEvent.coordinate, mapBrowserEvent));
      return true;
    } else {
      return false;
    }
  }
  
  
  export default DragBox;
  