import { isHTMLElement, $, addDisposableListener, EventType } from "../../../base/browser/dom.mjs";
import { StandardMouseEvent } from "../../../base/browser/mouseEvent.mjs";
import { Menu } from "../../../base/browser/ui/menu/menu.mjs";
import { ActionRunner } from "../../../base/common/actions.mjs";
import { isCancellationError } from "../../../base/common/errors.mjs";
import { DisposableStore, combinedDisposable } from "../../../base/common/lifecycle.mjs";
import "./contextMenuHandler.css.mjs";
import { attachMenuStyler } from "../../theme/common/styler.mjs";
class ContextMenuHandler {
  constructor(contextViewService, telemetryService, notificationService, keybindingService, themeService) {
    this.contextViewService = contextViewService;
    this.telemetryService = telemetryService;
    this.notificationService = notificationService;
    this.keybindingService = keybindingService;
    this.themeService = themeService;
    this.focusToReturn = null;
    this.block = null;
    this.options = { blockMouse: true };
  }
  configure(options) {
    this.options = options;
  }
  showContextMenu(delegate) {
    const actions = delegate.getActions();
    if (!actions.length) {
      return;
    }
    this.focusToReturn = document.activeElement;
    let menu;
    let shadowRootElement = isHTMLElement(delegate.domForShadowRoot) ? delegate.domForShadowRoot : void 0;
    this.contextViewService.showContextView({
      getAnchor: () => delegate.getAnchor(),
      canRelayout: false,
      anchorAlignment: delegate.anchorAlignment,
      anchorAxisAlignment: delegate.anchorAxisAlignment,
      render: (container) => {
        let className = delegate.getMenuClassName ? delegate.getMenuClassName() : "";
        if (className) {
          container.className += " " + className;
        }
        if (this.options.blockMouse) {
          this.block = container.appendChild($(".context-view-block"));
          this.block.style.position = "fixed";
          this.block.style.cursor = "initial";
          this.block.style.left = "0";
          this.block.style.top = "0";
          this.block.style.width = "100%";
          this.block.style.height = "100%";
          this.block.style.zIndex = "-1";
          addDisposableListener(this.block, EventType.MOUSE_DOWN, (e) => e.stopPropagation());
        }
        const menuDisposables = new DisposableStore();
        const actionRunner = delegate.actionRunner || new ActionRunner();
        actionRunner.onBeforeRun(this.onActionRun, this, menuDisposables);
        actionRunner.onDidRun(this.onDidActionRun, this, menuDisposables);
        menu = new Menu(container, actions, {
          actionViewItemProvider: delegate.getActionViewItem,
          context: delegate.getActionsContext ? delegate.getActionsContext() : null,
          actionRunner,
          getKeyBinding: delegate.getKeyBinding ? delegate.getKeyBinding : (action) => this.keybindingService.lookupKeybinding(action.id)
        });
        menuDisposables.add(attachMenuStyler(menu, this.themeService));
        menu.onDidCancel(() => this.contextViewService.hideContextView(true), null, menuDisposables);
        menu.onDidBlur(() => this.contextViewService.hideContextView(true), null, menuDisposables);
        menuDisposables.add(addDisposableListener(window, EventType.BLUR, () => this.contextViewService.hideContextView(true)));
        menuDisposables.add(addDisposableListener(window, EventType.MOUSE_DOWN, (e) => {
          if (e.defaultPrevented) {
            return;
          }
          let event = new StandardMouseEvent(e);
          let element = event.target;
          if (event.rightButton) {
            return;
          }
          while (element) {
            if (element === container) {
              return;
            }
            element = element.parentElement;
          }
          this.contextViewService.hideContextView(true);
        }));
        return combinedDisposable(menuDisposables, menu);
      },
      focus: () => {
        if (menu) {
          menu.focus(!!delegate.autoSelectFirstItem);
        }
      },
      onHide: (didCancel) => {
        if (delegate.onHide) {
          delegate.onHide(!!didCancel);
        }
        if (this.block) {
          this.block.remove();
          this.block = null;
        }
        if (this.focusToReturn) {
          this.focusToReturn.focus();
        }
      }
    }, shadowRootElement, !!shadowRootElement);
  }
  onActionRun(e) {
    this.telemetryService.publicLog2("workbenchActionExecuted", { id: e.action.id, from: "contextMenu" });
    this.contextViewService.hideContextView(false);
    if (this.focusToReturn) {
      this.focusToReturn.focus();
    }
  }
  onDidActionRun(e) {
    if (e.error && !isCancellationError(e.error)) {
      this.notificationService.error(e.error);
    }
  }
}
export {
  ContextMenuHandler
};
