/* COPYRIGHT Esri - https://js.arcgis.com/5.0.18/LICENSE.txt */
import{clock as t}from"../../../core/clock.js";import{removeMaybe as e}from"../../../core/maybe.js";import{InputHandler as i}from"../InputHandler.js";import{getHoldAndDragParameters as o,euclideanDistance as n}from"./support.js";class r extends i{constructor(e={},i=t){super(!1),this._clock=i,this._pointerState=new Map,this._parameters=o(e),this._pointerDrag=this.registerOutgoing("pointer-drag"),this._immediateClick=this.registerOutgoing("immediate-click"),this._pointerHold=this.registerOutgoing("hold"),this.registerIncoming("pointer-down",t=>this._handlePointerDown(t)),this.registerIncoming("pointer-up",t=>this._handlePointerLoss(t,"pointer-up")),this.registerIncoming("pointer-capture-lost",t=>this._handlePointerLoss(t,"pointer-capture-lost")),this.registerIncoming("pointer-cancel",t=>this._handlePointerLoss(t,"pointer-cancel")),this._moveHandle=this.registerIncoming("pointer-move",t=>this._handlePointerMove(t)),this._moveHandle.pause()}onUninstall(){this._pointerState.forEach(t=>{t.holdTimeout=e(t.holdTimeout)}),super.onUninstall()}_handlePointerDown(t){const e=t.data,i=e.native.pointerId;let o=null;0===this._pointerState.size&&(o=this._clock.setTimeout(()=>{const e=this._pointerState.get(i);if(e){if(!e.isDragging){const i=e.previousEvent;this._pointerHold.emit(i,void 0,t.modifiers),e.holdEmitted=!0}e.holdTimeout=null}},this._parameters.holdDelay));const n={startEvent:e,previousEvent:e,startTimestamp:t.timestamp,isDragging:!1,downButton:e.native.button,holdTimeout:o,modifiers:new Set};this._pointerState.set(i,n),this.startCapturingPointer(e.native),this._moveHandle.resume(),this._pointerState.size>1&&this._startDragging(t)}_handlePointerMove(t){const e=t.data,i=e.native.pointerId,o=this._pointerState.get(i);if(o){if(o.isDragging)this._pointerDrag.emit(s("update",o,e),void 0,o.modifiers);else{n(e,o.startEvent)>this._getDragThreshold(e.native.pointerType)&&this._startDragging(t)}o.previousEvent=e}}_getDragThreshold(t){switch(t){case"touch":return this._parameters.movementUntilTouchDrag;case"pen":return this._parameters.movementUntilPenDrag;default:return this._parameters.movementUntilMouseDrag}}_startDragging(t){const e=t.data,i=e.native.pointerId;this._pointerState.forEach(o=>{null!=o.holdTimeout&&(o.holdTimeout.remove(),o.holdTimeout=null),o.isDragging||(o.modifiers=t.modifiers,o.isDragging=!0,i===o.startEvent.native.pointerId?this._pointerDrag.emit(s("start",o,e)):this._pointerDrag.emit(s("start",o,o.previousEvent),t.timestamp))})}_handlePointerLoss(t,e){const i=t.data,o=i.native.pointerId,n=this._pointerState.get(o);if(n){if(null!=n.holdTimeout&&(n.holdTimeout.remove(),n.holdTimeout=null),n.isDragging)this._pointerDrag.emit(s("end",n,"pointer-up"===e?i:n.previousEvent),void 0,n.modifiers);else if("pointer-up"===e&&n.downButton===i.native.button){t.timestamp-n.startTimestamp<=this._parameters.maximumClickDelay&&!n.holdEmitted&&this._immediateClick.emit(i)}this._pointerState.delete(o),this.stopCapturingPointer(i.native),0===this._pointerState.size&&this._moveHandle.pause()}}}function s(t,e,i){return{action:t,startEvent:e.startEvent,previousEvent:e.previousEvent,currentEvent:i}}export{r as PointerClickHoldAndDrag};
