/*
 * Copyright 2000-2012 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.openapi.actionSystem.impl;

import com.intellij.ide.DataManager;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.ActionPopupMenu;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationActivationListener;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.JBPopupMenu;
import com.intellij.openapi.util.Getter;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.ui.ScreenUtil;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import java.awt.*;

/**
 * @author Anton Katilin
 * @author Vladimir Kondratyev
 */
final class ActionPopupMenuImpl implements ActionPopupMenu, ApplicationActivationListener {

  private final MyMenu myMenu;
  private final ActionManagerImpl myManager;
  private MessageBusConnection myConnection;

  private final Application myApp;
  private IdeFrame myFrame;
  @Nullable private Getter<DataContext> myDataContextProvider;

  public ActionPopupMenuImpl(String place, @NotNull ActionGroup group, ActionManagerImpl actionManager, @Nullable PresentationFactory factory) {
    myManager = actionManager;
    myMenu = new MyMenu(place, group, factory);
    myApp = ApplicationManager.getApplication();
  }

  public JPopupMenu getComponent() {
    return myMenu;
  }

  public void setDataContextProvider(@Nullable Getter<DataContext> dataContextProvider) {
    myDataContextProvider = dataContextProvider;
  }

  private class MyMenu extends JBPopupMenu {
    private final String myPlace;
    private final ActionGroup myGroup;
    private DataContext myContext;
    private final PresentationFactory myPresentationFactory;

    public MyMenu(String place, @NotNull ActionGroup group, @Nullable PresentationFactory factory) {
      myPlace = place;
      myGroup = group;
      myPresentationFactory = factory != null ? factory : new MenuItemPresentationFactory();
      addPopupMenuListener(new MyPopupMenuListener());
    }

    public void show(final Component component, int x, int y) {
      if (!component.isShowing()) {
        //noinspection HardCodedStringLiteral
        throw new IllegalArgumentException("component must be shown on the screen");
      }

      removeAll();

      // Fill menu. Only after filling menu has non zero size.

      int x2 = Math.max(0, Math.min(x, component.getWidth() - 1)); // fit x into [0, width-1]
      int y2 = Math.max(0, Math.min(y, component.getHeight() - 1)); // fit y into [0, height-1]

      myContext = myDataContextProvider != null ? myDataContextProvider.get() : DataManager.getInstance().getDataContext(component, x2, y2);
      Utils.fillMenu(myGroup, this, true, myPresentationFactory, myContext, myPlace, false, false);
      if (getComponentCount() == 0) {
        return;
      }
      Dimension preferredSize = getPreferredSize();

      // Translate (x,y) into screen coordinate syetem

      int _x, _y; // these are screen coordinates of clicked point
      Point p = component.getLocationOnScreen();
      _x = p.x + x;
      _y = p.y + y;

      // Determine graphics device which contains our point

      GraphicsConfiguration targetGraphicsConfiguration = null;
      GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
      GraphicsDevice[] devices = env.getScreenDevices();
      for (GraphicsDevice device : devices) {
        GraphicsConfiguration graphicsConfiguration = device.getDefaultConfiguration();
        Rectangle r = graphicsConfiguration.getBounds();
        if (r.x <= _x && _x <= r.x + r.width && r.y <= _y && _y <= r.y + r.height) {
          targetGraphicsConfiguration = graphicsConfiguration;
          break;
        }
      }
      if (targetGraphicsConfiguration == null && devices.length > 0) {
        targetGraphicsConfiguration = env.getDefaultScreenDevice().getDefaultConfiguration();
      }
      if (targetGraphicsConfiguration == null) {
        //noinspection HardCodedStringLiteral
        throw new IllegalStateException("It's impossible to determine target graphics environment for point (" + _x + "," + _y + ")");
      }

      // Determine real client area of target graphics configuration
      Insets insets = ScreenUtil.getScreenInsets(targetGraphicsConfiguration);
      Rectangle targetRectangle = targetGraphicsConfiguration.getBounds();
      targetRectangle.x += insets.left;
      targetRectangle.y += insets.top;
      targetRectangle.width -= insets.left + insets.right;
      targetRectangle.height -= insets.top + insets.bottom;

      // Fit popup into targetRectangle.
      // The algorithm is the following:
      // First of all try to move menu up on its height. If menu's left-top corner
      // is inside screen bounds after that, then OK. Otherwise, if menu is too high
      // (left-top corner is outside of screen bounds) then try to move menu up on
      // not visible visible area height.
      if (_x + preferredSize.width > targetRectangle.x + targetRectangle.width) {
        x -= preferredSize.width;
      }
      if (_y + preferredSize.height > targetRectangle.y + targetRectangle.height) {
        int invisibleHeight = _y + preferredSize.height - targetRectangle.y - targetRectangle.height;
        y -= invisibleHeight;
      }

      if (myApp != null) {
        if (myApp.isActive()) {
          Component frame = UIUtil.findUltimateParent(component);
          if (frame instanceof IdeFrame) {
            myFrame = (IdeFrame)frame;
          }
          myConnection = myApp.getMessageBus().connect();
          myConnection.subscribe(ApplicationActivationListener.TOPIC, ActionPopupMenuImpl.this);
       }
      }

      super.show(component, x, y);
    }

    @Override
    public void setVisible(boolean b) {
      super.setVisible(b);
      if (!b) ReflectionUtil.resetField(this, "invoker");
    }

    private class MyPopupMenuListener implements PopupMenuListener {
      public void popupMenuCanceled(PopupMenuEvent e) {
        disposeMenu();
      }

      public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
        disposeMenu();
      }

      private void disposeMenu() {
        myManager.removeActionPopup(ActionPopupMenuImpl.this);
        MyMenu.this.removeAll();
        if (myConnection != null) {
          myConnection.disconnect();
        }
      }

      public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
        MyMenu.this.removeAll();
        Utils.fillMenu(myGroup, MyMenu.this, !UISettings.getInstance().DISABLE_MNEMONICS, myPresentationFactory, myContext, myPlace, false,
                       false);
        myManager.addActionPopup(ActionPopupMenuImpl.this);
      }
    }
  }

  @Override
  public void applicationActivated(IdeFrame ideFrame) {
  }

  @Override
  public void applicationDeactivated(IdeFrame ideFrame) {
    if (myFrame == ideFrame) {
      myMenu.setVisible(false);
    }
  }

}
