/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.ui.mac;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.impl.ModalityHelper;
import com.intellij.ui.mac.foundation.ID;
import com.intellij.ui.mac.foundation.MacUtil;
import com.intellij.util.ui.UIUtil;
import com.sun.jna.Callback;
import com.sun.jna.Pointer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import static com.intellij.ui.mac.foundation.Foundation.*;

/**
 * @author pegov
 */
public class MacMessagesImpl extends MacMessages {
  private static final Logger LOG = Logger.getInstance("#com.intellij.ui.mac.MacMessages");


  private static class MessageResult {
    MessageResult (int returnCode, boolean suppress) {
      myReturnCode = returnCode;
      mySuppress = suppress;
    }
    private final int myReturnCode;
    private final boolean mySuppress;
  }

  private static final Map<Window, MessageResult> resultsFromDocumentRoot = new HashMap<Window, MessageResult> ();
  private static final Map<Window, MacMessagesQueue<Runnable>> queuesFromDocumentRoot = new HashMap<Window, MacMessagesQueue<Runnable>>();

  private static final Callback SHEET_DID_END = new Callback() {
    @SuppressWarnings("UnusedDeclaration")
    public void callback(ID self, String selector, ID alert, ID returnCode, ID contextInfo) {
      synchronized (lock) {
        Window documentRoot = windowFromId.get(contextInfo.longValue());
        processResult(documentRoot);
        ID suppressState = invoke(invoke(alert, "suppressionButton"), "state");
        resultsFromDocumentRoot.put(documentRoot, new MessageResult(returnCode.intValue(), suppressState.intValue() == 1));
        queuesFromDocumentRoot.get(windowFromId.get(contextInfo.longValue())).runFromQueue();
      }
      JDK7WindowReorderingWorkaround.enableReordering();
      cfRelease(self);
    }
  };

  private static final Callback VARIABLE_BUTTONS_SHEET_PANEL = new Callback() {
    @SuppressWarnings("UnusedDeclaration")
    public void callback(ID self, String selector, ID params) {
      ID title = invoke(params, "objectAtIndex:", 0);
      ID message = invoke(params, "objectAtIndex:", 1);
      ID focusedWindow = invoke(params, "objectAtIndex:", 2);
      ID alertStyle = invoke(params, "objectAtIndex:", 4);
      ID doNotAskText = invoke(params, "objectAtIndex:", 5);
      int defaultOptionIndex = Integer.parseInt(toStringViaUTF8(invoke(params, "objectAtIndex:", 6)));
      int focusedOptionIndex = Integer.parseInt(toStringViaUTF8(invoke(params, "objectAtIndex:", 7)));
      ID buttons = invoke(params, "objectAtIndex:", 8);
      ID doNotAskChecked = invoke(params, "objectAtIndex:", 9);

      ID alert = invoke(invoke("NSAlert", "alloc"), "init");

      invoke(alert, "setMessageText:", title);
      invoke(alert, "setInformativeText:", message);

      if ("error".equals(toStringViaUTF8(alertStyle))) {
        invoke(alert, "setAlertStyle:", 2); // NSCriticalAlertStyle = 2
      }

      final ID buttonEnumerator = invoke(buttons, "objectEnumerator");
      while (true) {
        final ID button = invoke(buttonEnumerator, "nextObject");
        if (0 == button.intValue()) break;
        invoke(alert, "addButtonWithTitle:", button);
      }

      if (defaultOptionIndex != -1) {
        invoke(invoke(alert, "window"), "setDefaultButtonCell:",
               invoke(invoke(invoke(alert, "buttons"), "objectAtIndex:", defaultOptionIndex), "cell"));
      }

      // it seems like asking for focus will cause java to go and query focus owner too, which may cause dead locks on main-thread
      //if (focusedOptionIndex != -1) {
      //  invoke(invoke(alert, "window"), "makeFirstResponder:",
      //         invoke(invoke(alert, "buttons"), "objectAtIndex:", focusedOptionIndex));
      //} else {
      //  int count = invoke(buttons, "count").intValue();
      //  invoke(invoke(alert, "window"), "makeFirstResponder:",
      //         invoke(invoke(alert, "buttons"), "objectAtIndex:", count == 1 ? 0 : 1));
      //}

      enableEscapeToCloseTheMessage(alert);

      String doNotAsk = toStringViaUTF8(doNotAskText);
      if (!"-1".equals(doNotAsk)) {
        invoke(alert, "setShowsSuppressionButton:", 1);
        invoke(invoke(alert, "suppressionButton"), "setTitle:", doNotAskText);
        invoke(invoke(alert, "suppressionButton"), "setState:", "checked".equals(toStringViaUTF8(doNotAskChecked)));
      }

      invoke(alert, "beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo:", focusedWindow, self,
             createSelector("alertDidEnd:returnCode:contextInfo:"), focusedWindow);
      cfRelease(alert);
    }
  };

  private static final Callback SIMPLE_SHEET_PANEL = new Callback() {
    @SuppressWarnings("UnusedDeclaration")
    public void callback(ID self, String selector, ID params) {
      ID title = invoke(params, "objectAtIndex:", 0);
      ID defaultText = invoke(params, "objectAtIndex:", 1);
      ID otherText = invoke(params, "objectAtIndex:", 2);
      ID alternateText = invoke(params, "objectAtIndex:", 3);
      ID message = invoke(params, "objectAtIndex:", 4);
      ID focusedWindow = invoke(params, "objectAtIndex:", 5);
      ID alertStyle = invoke(params, "objectAtIndex:", 7);
      ID doNotAskText = invoke(params, "objectAtIndex:", 8);
      ID doNotAskChecked = invoke(params, "objectAtIndex:", 9);

      boolean alternateExist = !"-1".equals(toStringViaUTF8(alternateText));
      boolean otherExist = !"-1".equals(toStringViaUTF8(otherText));

      final ID alert = invoke("NSAlert", "alertWithMessageText:defaultButton:alternateButton:otherButton:informativeTextWithFormat:",
                              title, defaultText, alternateExist ? alternateText : null, otherExist ? otherText : null, message);

      if ("error".equals(toStringViaUTF8(alertStyle))) {
        invoke(alert, "setAlertStyle:", 2); // NSCriticalAlertStyle = 2
      }

      // it seems like asking for focus will cause java to go and query focus owner too, which may cause dead locks on main-thread
      //ID window = invoke(alert, "window");
      //invoke(window, "makeFirstResponder:",
      //       invoke(invoke(alert, "buttons"), "objectAtIndex:", alternateExist ? 2 : otherExist ? 1 : 0));
      //

      if (!alternateExist) {
        enableEscapeToCloseTheMessage(alert);
      }

      String doNotAsk = toStringViaUTF8(doNotAskText);
      if (!"-1".equals(doNotAsk)) {
        invoke(alert, "setShowsSuppressionButton:", 1);
        invoke(invoke(alert, "suppressionButton"), "setTitle:", doNotAskText);
        invoke(invoke(alert, "suppressionButton"), "setState:", "checked".equals(toStringViaUTF8(doNotAskChecked)));
      }

      invoke(alert, "beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo:", focusedWindow, self,
             createSelector("alertDidEnd:returnCode:contextInfo:"), focusedWindow);
    }
  };

  private static void processResult(Window w) {
    synchronized (lock) {
      if (!blockedDocumentRoots.keySet().contains(w)) {
        throw new RuntimeException("Window should be in th list.");
      }

      int openedSheetsForWindow = blockedDocumentRoots.get(w);

      if (openedSheetsForWindow < 1) {
        throw new RuntimeException("We should have at least one window in the list");
      }

      if (openedSheetsForWindow == 1) {
        // The last sheet
        blockedDocumentRoots.remove(w);
      } else {
        blockedDocumentRoots.put(w, openedSheetsForWindow - 1);
      }

    }
  }

  private static void enableEscapeToCloseTheMessage(ID alert) {
    int buttonsNumber = invoke(invoke(alert, "buttons"), "count").intValue();
    if (buttonsNumber < 2) return;
    invoke(invoke(invoke(alert, "buttons"), "objectAtIndex:",
                  buttonsNumber - 1), "setKeyEquivalent:",  nsString("\033"));
  }

  private MacMessagesImpl() {}

  private static final Callback windowDidBecomeMainCallback = new Callback() {
    @SuppressWarnings("UnusedDeclaration") // this is a native up-call
    public void callback(ID self,
                         ID nsNotification)
    {
      synchronized (lock) {
        if (!windowFromId.keySet().contains(self.longValue())) {
          return;
        }
      }
      invoke(self, "oldWindowDidBecomeMain:", nsNotification);
    }
  };

  static {
    if (SystemInfo.isMac) {
      final ID delegateClass = allocateObjcClassPair(getObjcClass("NSObject"), "NSAlertDelegate_");
      if (!addMethod(delegateClass, createSelector("alertDidEnd:returnCode:contextInfo:"), SHEET_DID_END, "v*")) {
        throw new RuntimeException("Unable to add method to objective-c delegate class!");
      }
      if (!addMethod(delegateClass, createSelector("showSheet:"), SIMPLE_SHEET_PANEL, "v*")) {
        throw new RuntimeException("Unable to add method to objective-c delegate class!");
      }
      if (!addMethod(delegateClass, createSelector("showVariableButtonsSheet:"), VARIABLE_BUTTONS_SHEET_PANEL, "v*")) {
        throw new RuntimeException("Unable to add method to objective-c delegate class!");
      }
      registerObjcClassPair(delegateClass);

      if (SystemInfo.isJavaVersionAtLeast("1.7")) {

        ID awtWindow = getObjcClass("AWTWindow");

        Pointer windowWillEnterFullScreenMethod = createSelector("windowDidBecomeMain:");
        ID originalWindowWillEnterFullScreen = class_replaceMethod(awtWindow, windowWillEnterFullScreenMethod,
                                                                   windowDidBecomeMainCallback, "v@::@");

        addMethodByID(awtWindow, createSelector("oldWindowDidBecomeMain:"),
                      originalWindowWillEnterFullScreen, "v@::@");

      }
    }
  }

  @Override
  public void showOkMessageDialog(@NotNull String title, String message, @NotNull String okText, @Nullable Window window) {
    showAlertDialog(title, okText, null, null, message, window);
  }

  @Override
  public void showOkMessageDialog(@NotNull String title, String message, @NotNull String okText) {
    showAlertDialog(title, okText, null, null, message, null);
  }

  @Override
  @Messages.YesNoResult
  public int showYesNoDialog(@NotNull String title, String message, @NotNull String yesButton, @NotNull String noButton, @Nullable Window window) {
    return showAlertDialog(title, yesButton, null, noButton, message, window) == Messages.YES ? Messages.YES : Messages.NO;
  }

  @Override
  @Messages.YesNoResult
  public int showYesNoDialog(@NotNull String title, String message, @NotNull String yesButton, @NotNull String noButton, @Nullable Window window,
                             @Nullable DialogWrapper.DoNotAskOption doNotAskDialogOption) {
    return showAlertDialog(title, yesButton, null, noButton, message, window, false, doNotAskDialogOption) == Messages.YES ? Messages.YES : Messages.NO;
  }

  @Override
  public void showErrorDialog(@NotNull String title, String message, @NotNull String okButton, @Nullable Window window) {
    showAlertDialog(title, okButton, null, null, message, window, true, null);
  }

  @Override
  @Messages.YesNoCancelResult
  public int showYesNoCancelDialog(@NotNull String title,
                                   String message,
                                   @NotNull String defaultButton,
                                   String alternateButton,
                                   String otherButton,
                                   Window window,
                                   @Nullable DialogWrapper.DoNotAskOption doNotAskOption) {
    return showAlertDialog(title, defaultButton, alternateButton, otherButton, message, window, false, doNotAskOption);
  }

  private static final Object lock = new Object();

  private static final HashMap<Window, Integer> blockedDocumentRoots = new HashMap<Window, Integer>();

  private static final HashMap<Long, Window> windowFromId = new HashMap<Long, Window>();

  public static void pumpEventsDocumentExclusively (Window documentRoot) {

    Integer messageNumber = blockedDocumentRoots.get(documentRoot);

    EventQueue theQueue = documentRoot.getToolkit().getSystemEventQueue();

    do {
      try {
        AWTEvent event = theQueue.getNextEvent();
        boolean eventOk = true;
        if (event instanceof InputEvent) {
          final Object s = event.getSource();
          if (s instanceof Component) {
            Component c = (Component)s;

            Window w = findDocumentRoot(c);
            if (w == documentRoot) {
              eventOk = false;
              ((InputEvent)event).consume();
            }
          }
        }

        if (eventOk) {
          Class<?>[] paramString = new Class<?>[1];
          paramString[0] = AWTEvent.class;
          Method method = theQueue.getClass().getDeclaredMethod("dispatchEvent",paramString);
          method.setAccessible(true);
          method.invoke(theQueue, event);
        }
      }
      catch (MacMessageException mme) {
        throw mme;
      }
      catch (Throwable e) {
        LOG.error(e);
      }
    }
    while (isBlockedDocumentRoot(documentRoot, messageNumber));
  }

  private static boolean isBlockedDocumentRoot(Window documentRoot, Integer messageNumber) {
    synchronized (lock) {
      return messageNumber.equals(blockedDocumentRoots.get(documentRoot));
    }
  }

  private static Window findDocumentRoot (final Component c) {
    if (c == null) return null;
    Window w = c instanceof Window ? (Window)c : getContainingWindow(c);
    synchronized (c.getTreeLock()) {
      while (w.getOwner() != null) {
        w = w.getOwner();
      }
    }
    return w;
  }

  // This method is not available in jdk 1.6.0_6. Should be changed to the JDK implementation
  // as soon as we will have switched on JDK 7.
  private static Window getContainingWindow(Component comp) {
    while (comp != null && !(comp instanceof Window)) {
      comp = comp.getParent();
    }
    return (Window)comp;
  }

  private static void startModal(final Window w, ID windowId) {
    long windowPtr = windowId.longValue();
    synchronized (lock) {
      JDK7WindowReorderingWorkaround.disableReordering();
      windowFromId.put(windowPtr, w);
      if (blockedDocumentRoots.keySet().contains(w)) {
        blockedDocumentRoots.put(w, blockedDocumentRoots.get(w) + 1);
      } else {
        blockedDocumentRoots.put(w, 1);
      }
    }

    pumpEventsDocumentExclusively(w);
    synchronized (lock) {
      windowFromId.remove(windowPtr);
    }
  }

  private enum COMMON_DIALOG_PARAM_TYPE {
    title,
    message,
    errorStyle,
    doNotAskDialogOption1,
    doNotAskDialogOption2,
    nativeFocusedWindow
  }

  private enum MESSAGE_DIALOG_PARAM_TYPE {
    buttonsArray,
    defaultOptionIndex,
    focusedOptionIndex
  }

  private enum ALERT_DIALOG_PARAM_TYPE {
    defaultText,
    alternateText,
    otherText
  }

  private static class DialogParamsWrapper {
    private ID window = null;
    private final Map<Enum, Object> params;
    private final DialogType dialogType;

    private enum DialogType {
      alert,
      message
    }

    private DialogParamsWrapper(@NotNull DialogType t, @NotNull Map<Enum, Object> p) {
      dialogType = t;
      params = p;
    }

    private void setNativeWindow (final ID w) {
      window = w;
    }

    private ID getParamsAsID() {
      if (window == null) {
        throw new MacMessageException("Window should be in the list.");
      }
      params.put(COMMON_DIALOG_PARAM_TYPE.nativeFocusedWindow, window);

      ID paramsAsID = null;

      switch (dialogType) {
        case alert:
          paramsAsID = getParamsForAlertDialog(params);
          break;
        case message:
          paramsAsID = getParamsForMessageDialog(params);
          break;
      }
      return paramsAsID;
    }


    private static ID getParamsForAlertDialog(@NotNull Map<Enum, Object> params) {
      return invoke("NSArray", "arrayWithObjects:",
                    params.get(COMMON_DIALOG_PARAM_TYPE.title),
                    params.get(ALERT_DIALOG_PARAM_TYPE.defaultText),
                    params.get(ALERT_DIALOG_PARAM_TYPE.alternateText),
                    params.get(ALERT_DIALOG_PARAM_TYPE.otherText),
                    params.get(COMMON_DIALOG_PARAM_TYPE.message),
                    params.get(COMMON_DIALOG_PARAM_TYPE.nativeFocusedWindow),
                    nsString(""),
                    params.get(COMMON_DIALOG_PARAM_TYPE.errorStyle),
                    params.get(COMMON_DIALOG_PARAM_TYPE.doNotAskDialogOption1),
                    params.get(COMMON_DIALOG_PARAM_TYPE.doNotAskDialogOption2),
                    null);
    }

    private static ID getParamsForMessageDialog(@NotNull Map<Enum, Object> params) {
      return invoke("NSArray", "arrayWithObjects:",
                    params.get(COMMON_DIALOG_PARAM_TYPE.title),
                    params.get(COMMON_DIALOG_PARAM_TYPE.message),
                    params.get(COMMON_DIALOG_PARAM_TYPE.nativeFocusedWindow),
                    nsString(""),
                    params.get(COMMON_DIALOG_PARAM_TYPE.errorStyle),
                    params.get(COMMON_DIALOG_PARAM_TYPE.doNotAskDialogOption1),
                    params.get(MESSAGE_DIALOG_PARAM_TYPE.defaultOptionIndex),
                    params.get(MESSAGE_DIALOG_PARAM_TYPE.focusedOptionIndex),
                    params.get(MESSAGE_DIALOG_PARAM_TYPE.buttonsArray),
                    params.get(COMMON_DIALOG_PARAM_TYPE.doNotAskDialogOption2),
                    null);
    }
  }

  @Messages.YesNoCancelResult
  public static int showAlertDialog(@NotNull String title,
                                    @NotNull String defaultText,
                                    @Nullable final String alternateText,
                                    @Nullable final String otherText,
                                    final String message,
                                    @Nullable Window window,
                                    final boolean errorStyle,
                                    @Nullable final DialogWrapper.DoNotAskOption doNotAskDialogOption) {

    Map<Enum, Object> params  = new HashMap<Enum, Object> ();

    ID pool = invoke(invoke("NSAutoreleasePool", "alloc"), "init");
    try {
      params.put(COMMON_DIALOG_PARAM_TYPE.title, nsString(title));
      params.put(ALERT_DIALOG_PARAM_TYPE.defaultText, nsString(UIUtil.removeMnemonic(defaultText)));
      params.put(ALERT_DIALOG_PARAM_TYPE.alternateText, nsString(otherText == null ? "-1" : UIUtil.removeMnemonic(otherText)));
      params.put(ALERT_DIALOG_PARAM_TYPE.otherText, nsString(alternateText == null ? "-1" : UIUtil.removeMnemonic(alternateText)));
      // replace % -> %% to avoid formatted parameters (causes SIGTERM)
      params.put(COMMON_DIALOG_PARAM_TYPE.message, nsString(StringUtil.stripHtml(message == null ? "" : message, true).replace("%", "%%")));
      params.put(COMMON_DIALOG_PARAM_TYPE.errorStyle, nsString(errorStyle ? "error" : "-1"));
      params.put(COMMON_DIALOG_PARAM_TYPE.doNotAskDialogOption1, nsString(doNotAskDialogOption == null || !doNotAskDialogOption.canBeHidden()
                                                                          // TODO: state=!doNotAsk.shouldBeShown()
                                                                          ? "-1"
                                                                          : doNotAskDialogOption.getDoNotShowMessage()));
      params.put(COMMON_DIALOG_PARAM_TYPE.doNotAskDialogOption2, nsString(doNotAskDialogOption != null
                                                                          && !doNotAskDialogOption.isToBeShown() ? "checked" : "-1"));
      MessageResult result = resultsFromDocumentRoot.remove(
        showDialog(window, "showSheet:", new DialogParamsWrapper(DialogParamsWrapper.DialogType.alert, params)));

      int convertedResult = convertReturnCodeFromNativeAlertDialog(result.myReturnCode, alternateText);

      if (doNotAskDialogOption != null && doNotAskDialogOption.canBeHidden()) {
        boolean operationCanceled = convertedResult == Messages.CANCEL;
        if (!operationCanceled || doNotAskDialogOption.shouldSaveOptionsOnCancel()) {
          doNotAskDialogOption.setToBeShown(!result.mySuppress, convertedResult);
        }
      }

      return convertedResult;
    }
    finally {
      invoke(pool, "release");
    }
  }

  @Override
  public int showMessageDialog(@NotNull final String title,
                               final String message,
                               @NotNull final String[] buttons,
                               final boolean errorStyle,
                               @Nullable Window window,
                               final int defaultOptionIndex,
                               final int focusedOptionIndex,
                               @Nullable final DialogWrapper.DoNotAskOption doNotAskDialogOption) {
    ID pool = invoke(invoke("NSAutoreleasePool", "alloc"), "init");
    try {
      final ID buttonsArray = invoke("NSMutableArray", "array");
      for (String s : buttons) {
        ID s1 = nsString(UIUtil.removeMnemonic(s));
        invoke(buttonsArray, "addObject:", s1);
      }

      Map<Enum, Object> params  = new HashMap<Enum, Object>();

      params.put(COMMON_DIALOG_PARAM_TYPE.title, nsString(title));
      // replace % -> %% to avoid formatted parameters (causes SIGTERM)
      params.put(COMMON_DIALOG_PARAM_TYPE.message, nsString(StringUtil.stripHtml(message == null ? "" : message, true).replace("%", "%%")));

      params.put(COMMON_DIALOG_PARAM_TYPE.errorStyle, nsString(errorStyle ? "error" : "-1"));
      params.put(COMMON_DIALOG_PARAM_TYPE.doNotAskDialogOption1, nsString(doNotAskDialogOption == null || !doNotAskDialogOption.canBeHidden()
                                                                          // TODO: state=!doNotAsk.shouldBeShown()
                                                                          ? "-1"
                                                                          : doNotAskDialogOption.getDoNotShowMessage()));
      params.put(COMMON_DIALOG_PARAM_TYPE.doNotAskDialogOption2, nsString(doNotAskDialogOption != null && !doNotAskDialogOption.isToBeShown() ? "checked" : "-1"));
      params.put(MESSAGE_DIALOG_PARAM_TYPE.defaultOptionIndex, nsString(Integer.toString(defaultOptionIndex)));
      params.put(MESSAGE_DIALOG_PARAM_TYPE.focusedOptionIndex, nsString(Integer.toString(focusedOptionIndex)));
      params.put(MESSAGE_DIALOG_PARAM_TYPE.buttonsArray, buttonsArray);

      MessageResult result = resultsFromDocumentRoot.remove(showDialog(window, "showVariableButtonsSheet:",
                                                                       new DialogParamsWrapper(DialogParamsWrapper.DialogType.message, params)));

      final int code = convertReturnCodeFromNativeMessageDialog(result.myReturnCode);

      final int cancelCode = buttons.length - 1;

      if (doNotAskDialogOption != null && doNotAskDialogOption.canBeHidden()) {
        if (cancelCode != code || doNotAskDialogOption.shouldSaveOptionsOnCancel()) {
          doNotAskDialogOption.setToBeShown(!result.mySuppress, code);
        }
      }

      return code;
    }
    finally {
      invoke(pool, "release");
    }
  }

  //title, message, errorStyle, window, paramsArray, doNotAskDialogOption, "showVariableButtonsSheet:"
  private static Window showDialog(@Nullable Window window, final String methodName, final DialogParamsWrapper paramsWrapper) {

    final Window foremostWindow = getForemostWindow(window);

    final Window documentRoot = getDocumentRootFromWindow(foremostWindow);

    final ID nativeFocusedWindow = MacUtil.findWindowFromJavaWindow(foremostWindow);

    paramsWrapper.setNativeWindow(nativeFocusedWindow);

    final ID paramsArray = paramsWrapper.getParamsAsID();

    foremostWindow.addWindowListener(new WindowAdapter() {
      @Override
      public void windowClosed(WindowEvent e) {
        super.windowClosed(e);
        //if (blockedDocumentRoots.get(documentRoot) != null) {
        //   LOG.assertTrue(blockedDocumentRoots.get(documentRoot) < 2);
        //}
        queuesFromDocumentRoot.remove(documentRoot);
        if (blockedDocumentRoots.remove(documentRoot) != null) {
          throw new MacMessageException("Owner window has been removed");
        }
      }
    });

    final ID delegate = invoke(invoke(getObjcClass("NSAlertDelegate_"), "alloc"), "init");

    IdeFocusManager.getGlobalInstance().setTypeaheadEnabled(false);

    runOrPostponeForWindow(documentRoot, new Runnable() {
      @Override
      public void run() {
        invoke(delegate, "performSelectorOnMainThread:withObject:waitUntilDone:",
               createSelector(methodName), paramsArray, false);
      }
    });

    startModal(documentRoot, nativeFocusedWindow);

    IdeFocusManager.getGlobalInstance().setTypeaheadEnabled(true);
    return documentRoot;
  }

  private static int convertReturnCodeFromNativeMessageDialog(int result) {
    return result - 1000;
  }

  @Messages.YesNoCancelResult
  private static int convertReturnCodeFromNativeAlertDialog(int returnCode, String alternateText) {
    // DEFAULT = 1
    // ALTERNATE = 0
    // OTHER = -1 (cancel)

    int cancelCode;
    int code;
    if (alternateText != null) {
      // DEFAULT = 0
      // ALTERNATE = 1
      // CANCEL = 2

      cancelCode = Messages.CANCEL;

      switch (returnCode) {
        case 1:
          code = Messages.YES;
          break;
        case 0:
          code = Messages.NO;
          break;
        case -1: // cancel
        default:
          code = Messages.CANCEL;
          break;
      }
    }
    else {
      // DEFAULT = 0
      // CANCEL = 1

      cancelCode = 1;

      switch (returnCode) {
        case 1:
          code = Messages.YES;
          break;
        case -1: // cancel
        default:
          code = Messages.NO;
          break;
      }
    }

    if (cancelCode == code) {
      code = Messages.CANCEL;
    }
    LOG.assertTrue(code == Messages.YES || code == Messages.NO || code == Messages.CANCEL, code);
    return code;
  }

  private static void runOrPostponeForWindow(Window documentRoot, Runnable task) {
    synchronized (lock) {
      MacMessagesQueue<Runnable> queue = queuesFromDocumentRoot.get(documentRoot);

      if (queue == null) {
        queue = new MacMessagesQueue<Runnable>();
        queuesFromDocumentRoot.put(documentRoot, queue);
      }

      queue.runOrEnqueue(task);
    }
  }

  private static Window getForemostWindow(final Window window) {
    Window _window = null;
    IdeFocusManager ideFocusManager = IdeFocusManager.getGlobalInstance();

    Component focusOwner = IdeFocusManager.findInstance().getFocusOwner();
    // Let's ask for a focused component first
    if (focusOwner != null) {
      _window = SwingUtilities.getWindowAncestor(focusOwner);
    }

    if (_window == null) {
      // Looks like ide lost focus, let's ask about the last focused component
      focusOwner = ideFocusManager.getLastFocusedFor(ideFocusManager.getLastFocusedFrame());
      if (focusOwner != null) {
        _window = SwingUtilities.getWindowAncestor(focusOwner);
      }
    }

    if (_window == null) {
      _window = WindowManager.getInstance().findVisibleFrame();
    }

    if (_window == null && window != null) {
      // It might be we just has not opened a frame yet.
      // So let's ask AWT
      focusOwner = window.getMostRecentFocusOwner();
      if (focusOwner != null) {
        _window = SwingUtilities.getWindowAncestor(focusOwner);
      }
    }

    if (_window != null) {
      // We have successfully found the window
      // Let's check that we have not missed a blocker
      if (ModalityHelper.isModalBlocked(_window)) {
        _window = ModalityHelper.getModalBlockerFor(_window);
      }
    }

    if (SystemInfo.isAppleJvm && MacUtil.getWindowTitle(_window) == null) {
      // With Apple JDK we cannot find a window if it does not have a title
      // Let's show a dialog instead of the message.
      throw new MacMessageException("MacMessage parent does not have a title.");
    }
    while (_window != null && MacUtil.getWindowTitle(_window) == null) {
      _window = _window.getOwner();
      //At least our frame should have a title
    }

    while (Registry.is("skip.untitled.windows.for.mac.messages") && _window != null && _window instanceof JDialog && !((JDialog)_window).isModal()) {
      _window = _window.getOwner();
    }

    return _window;
  }

  /**
   * Document root is intended to queue messages per a document root
   */
  private static Window getDocumentRootFromWindow(Window window) {
    return findDocumentRoot(window);
  }

  @Messages.YesNoCancelResult
  private static int showAlertDialog(@NotNull String title,
                                     @NotNull String okText,
                                     @Nullable String alternateText,
                                     @Nullable String cancelText,
                                     String message,
                                     @Nullable Window window) {
    return showAlertDialog(title, okText, alternateText, cancelText, message, window, false, null);
  }
}
