import { getShadowRoot, addDisposableThrottledListener, addDisposableListener } from "./dom.mjs";
import { IframeUtils } from "./iframe.mjs";
import { StandardMouseEvent } from "./mouseEvent.mjs";
import { DisposableStore } from "../common/lifecycle.mjs";
import { isIOS } from "../common/platform.mjs";
function standardMouseMoveMerger(lastEvent, currentEvent) {
  let ev = new StandardMouseEvent(currentEvent);
  ev.preventDefault();
  return {
    leftButton: ev.leftButton,
    buttons: ev.buttons,
    posx: ev.posx,
    posy: ev.posy
  };
}
class GlobalMouseMoveMonitor {
  constructor() {
    this._hooks = new DisposableStore();
    this._mouseMoveEventMerger = null;
    this._mouseMoveCallback = null;
    this._onStopCallback = null;
  }
  dispose() {
    this.stopMonitoring(false);
    this._hooks.dispose();
  }
  stopMonitoring(invokeStopCallback, browserEvent) {
    if (!this.isMonitoring()) {
      return;
    }
    this._hooks.clear();
    this._mouseMoveEventMerger = null;
    this._mouseMoveCallback = null;
    const onStopCallback = this._onStopCallback;
    this._onStopCallback = null;
    if (invokeStopCallback && onStopCallback) {
      onStopCallback(browserEvent);
    }
  }
  isMonitoring() {
    return !!this._mouseMoveEventMerger;
  }
  startMonitoring(initialElement, initialButtons, mouseMoveEventMerger, mouseMoveCallback, onStopCallback) {
    if (this.isMonitoring()) {
      return;
    }
    this._mouseMoveEventMerger = mouseMoveEventMerger;
    this._mouseMoveCallback = mouseMoveCallback;
    this._onStopCallback = onStopCallback;
    const windowChain = IframeUtils.getSameOriginWindowChain();
    const mouseMove = isIOS ? "pointermove" : "mousemove";
    const mouseUp = "mouseup";
    const listenTo = windowChain.map((element) => element.window.document);
    const shadowRoot = getShadowRoot(initialElement);
    if (shadowRoot) {
      listenTo.unshift(shadowRoot);
    }
    for (const element of listenTo) {
      this._hooks.add(addDisposableThrottledListener(element, mouseMove, (data) => {
        if (data.buttons !== initialButtons) {
          this.stopMonitoring(true);
          return;
        }
        this._mouseMoveCallback(data);
      }, (lastEvent, currentEvent) => this._mouseMoveEventMerger(lastEvent, currentEvent)));
      this._hooks.add(addDisposableListener(element, mouseUp, (e) => this.stopMonitoring(true)));
    }
    if (IframeUtils.hasDifferentOriginAncestor()) {
      let lastSameOriginAncestor = windowChain[windowChain.length - 1];
      this._hooks.add(addDisposableListener(lastSameOriginAncestor.window.document, "mouseout", (browserEvent) => {
        let e = new StandardMouseEvent(browserEvent);
        if (e.target.tagName.toLowerCase() === "html") {
          this.stopMonitoring(true);
        }
      }));
      this._hooks.add(addDisposableListener(lastSameOriginAncestor.window.document, "mouseover", (browserEvent) => {
        let e = new StandardMouseEvent(browserEvent);
        if (e.target.tagName.toLowerCase() === "html") {
          this.stopMonitoring(true);
        }
      }));
      this._hooks.add(addDisposableListener(lastSameOriginAncestor.window.document.body, "mouseleave", (browserEvent) => {
        this.stopMonitoring(true);
      }));
    }
  }
}
export {
  GlobalMouseMoveMonitor,
  standardMouseMoveMerger
};
