/*
 * 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.openapi.wm.impl;

import com.intellij.ide.IdeEventQueue;
import com.intellij.ide.IdeTooltipManager;
import com.intellij.ide.dnd.DnDAware;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ui.Divider;
import com.intellij.openapi.ui.Painter;
import com.intellij.openapi.ui.impl.GlassPaneDialogWrapperPeer;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Weighted;
import com.intellij.openapi.wm.IdeGlassPane;
import com.intellij.openapi.wm.IdeGlassPaneUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.event.MenuDragMouseEvent;
import javax.swing.text.html.HTMLEditorKit;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;

public class IdeGlassPaneImpl extends JPanel implements IdeGlassPaneEx, IdeEventQueue.EventDispatcher, Painter.Listener {

  private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.IdeGlassPaneImpl");

  private final List<EventListener> myMouseListeners = new ArrayList<EventListener>();
  private final Set<EventListener> mySortedMouseListeners = new TreeSet<EventListener>(new Comparator<EventListener>() {
    @Override
    public int compare(EventListener o1, EventListener o2) {
      double weight1 = 0;
      double weight2 = 0;
      if (o1 instanceof Weighted) {
        weight1 = ((Weighted)o1).getWeight();
      }
      if (o2 instanceof Weighted) {
        weight2 = ((Weighted)o2).getWeight();
      }
      return weight1 > weight2 ? 1 : weight1 < weight2 ? -1 : myMouseListeners.indexOf(o1) - myMouseListeners.indexOf(o2);
    }
  });
  private final JRootPane myRootPane;

  private final Set<Painter> myPainters = new LinkedHashSet<Painter>();
  private final Map<Painter, Component> myPainter2Component = new LinkedHashMap<Painter, Component>();

  private boolean myPaintingActive;
  private boolean myPreprocessorActive;
  private final Map<Object, Cursor> myListener2Cursor = new LinkedHashMap<Object, Cursor>();

  private Component myLastCursorComponent;
  private Cursor myLastOriginalCursor;
  private MouseEvent myPrevPressEvent;

  private JPanel myFocusProxy = new JPanel(){
    @Override
    public String toString() {
      return "FocusProxy";
    }
  };

  public IdeGlassPaneImpl(JRootPane rootPane) {
    myRootPane = rootPane;
    setOpaque(false);
    setVisible(false);
    setLayout(null);

    myFocusProxy.setOpaque(false);
    myFocusProxy.setPreferredSize(new Dimension(0, 0));
    myFocusProxy.setFocusable(true);
    UIUtil.setFocusProxy(myFocusProxy, true);
  }

  @Override
  public void addNotify() {
    super.addNotify();

    if (myFocusProxy.getParent() != null) {
      myFocusProxy.getParent().remove(myFocusProxy);
    }

    if (myFocusProxy.getParent() != getParent()) {
      getParent().add(myFocusProxy);
      myFocusProxy.setBounds(0, 0, 0, 0);
    }
  }

  public boolean dispatch(final AWTEvent e) {
    JRootPane eventRootPane = myRootPane;

    if (e instanceof MouseEvent) {
      MouseEvent me = (MouseEvent)e;
      Window eventWindow =
        me.getComponent() instanceof Window ? (Window)me.getComponent() : SwingUtilities.getWindowAncestor(me.getComponent());

      if (isContextMenu(eventWindow)) return false;

      final Window thisGlassWindow = SwingUtilities.getWindowAncestor(myRootPane);

      if (eventWindow instanceof JWindow) {
        eventRootPane = ((JWindow)eventWindow).getRootPane();
        if (eventRootPane != null) {
          if (!(eventRootPane.getGlassPane() instanceof IdeGlassPane)) {
            final Container parentWindow = eventWindow.getParent();
            if (parentWindow instanceof Window) {
              eventWindow = (Window)parentWindow;
            }
          }
        }
      }

      if (eventWindow != thisGlassWindow) return false;
    }


    if (e.getID() == MouseEvent.MOUSE_DRAGGED) {
      if (ApplicationManager.getApplication() != null) {
        IdeTooltipManager.getInstance().hideCurrent((MouseEvent)e, null, null);
      }
    }

    boolean dispatched;
    if (e.getID() == MouseEvent.MOUSE_PRESSED || e.getID() == MouseEvent.MOUSE_RELEASED || e.getID() == MouseEvent.MOUSE_CLICKED) {
      dispatched = preprocess((MouseEvent)e, false, eventRootPane);
    }
    else if (e.getID() == MouseEvent.MOUSE_MOVED || e.getID() == MouseEvent.MOUSE_DRAGGED) {
      dispatched = preprocess((MouseEvent)e, true, eventRootPane);
    }
    else if (e.getID() == MouseEvent.MOUSE_EXITED || e.getID() == MouseEvent.MOUSE_ENTERED) {
      dispatched = preprocess((MouseEvent)e, false, eventRootPane);
    }
    else {
      return false;
    }

    MouseEvent me = (MouseEvent)e;
    final Component meComponent = me.getComponent();
    if (!dispatched && meComponent != null) {
      final Window eventWindow = meComponent instanceof Window ? (Window)meComponent : SwingUtilities.getWindowAncestor(meComponent);
      if (eventWindow != SwingUtilities.getWindowAncestor(myRootPane)) {
        return false;
      }
      int button1 = MouseEvent.BUTTON1_MASK | MouseEvent.BUTTON1_DOWN_MASK;
      final boolean pureMouse1Event = (me.getModifiersEx() | button1) == button1;
      if (pureMouse1Event && me.getClickCount() <= 1 && !me.isPopupTrigger()) {
        final Point point = SwingUtilities.convertPoint(meComponent, me.getPoint(), myRootPane.getContentPane());
        JMenuBar menuBar = myRootPane.getJMenuBar();
        point.y += menuBar != null ? menuBar.getHeight() : 0;

        final Component target =
          SwingUtilities.getDeepestComponentAt(myRootPane.getContentPane().getParent(), point.x, point.y);
        if (target instanceof DnDAware) {
          final Point targetPoint = SwingUtilities.convertPoint(myRootPane.getContentPane().getParent(), point.x, point.y, target);
          final boolean overSelection = ((DnDAware)target).isOverSelection(targetPoint);
          if (overSelection) {
            final MouseListener[] listeners = target.getListeners(MouseListener.class);
            final MouseEvent mouseEvent = convertEvent(me, target);
            switch (me.getID()) {
              case MouseEvent.MOUSE_PRESSED:
                boolean consumed = false;
                if (target.isFocusable()) target.requestFocus();
                for (final MouseListener listener : listeners) {
                  final String className = listener.getClass().getName();
                  if (className.indexOf("BasicTreeUI$") >= 0 || className.indexOf("MacTreeUI$") >= 0) continue;
                  fireMouseEvent(listener, mouseEvent);
                  if (mouseEvent.isConsumed()) {
                    consumed = true;
                    break;
                  }
                }

                if (!mouseEvent.isConsumed()) {
                  final AWTEventListener[] eventListeners = Toolkit.getDefaultToolkit().getAWTEventListeners(MouseEvent.MOUSE_EVENT_MASK);
                  if (eventListeners != null && eventListeners.length > 0) {
                    for (final AWTEventListener eventListener : eventListeners) {
                      eventListener.eventDispatched(me);
                      if (me.isConsumed()) break;
                    }

                    if (me.isConsumed()) {
                      consumed = true;
                      break;
                    }
                  }
                }

                if (!consumed) {
                  myPrevPressEvent = mouseEvent;
                }
                else {
                  me.consume();
                }

                dispatched = true;
                break;
              case MouseEvent.MOUSE_RELEASED:
                if (myPrevPressEvent != null && myPrevPressEvent.getComponent() == target) {
                  for (final MouseListener listener : listeners) {
                    final String className = listener.getClass().getName();
                    if (className.indexOf("BasicTreeUI$") >= 0 || className.indexOf("MacTreeUI$") >= 0) {
                      fireMouseEvent(listener, myPrevPressEvent);
                      fireMouseEvent(listener, mouseEvent);
                      if (mouseEvent.isConsumed()) {
                        break;
                      }
                    }

                    fireMouseEvent(listener, mouseEvent);
                    if (mouseEvent.isConsumed()) {
                      break;
                    }
                  }

                  if (mouseEvent.isConsumed()) {
                    me.consume();
                  }

                  myPrevPressEvent = null;
                  dispatched = true;
                }
                break;
              default:
                myPrevPressEvent = null;
                break;
            }
          }
        }
      }
    }


    if (isVisible() && getComponentCount() == 0) {
      boolean cursorSet = false;
      if (meComponent != null) {
        final Point point = SwingUtilities.convertPoint(meComponent, me.getPoint(), myRootPane.getContentPane());

        if (myRootPane.getMenuBar() != null && myRootPane.getMenuBar().isVisible()) {
          point.y += myRootPane.getMenuBar().getHeight();
        }

        final Component target =
          SwingUtilities.getDeepestComponentAt(myRootPane.getContentPane().getParent(), point.x, point.y);
        if (target != null) {
          setCursor(target.getCursor());
          cursorSet = true;
        }
      }

      if (!cursorSet) {
        setCursor(Cursor.getDefaultCursor());
      }
    }

    return dispatched;
  }

  private static boolean isContextMenu(Window window) {
    if (window != null) {
      for (Component component : window.getComponents()) {
        if (component instanceof JComponent
            && UIUtil.findComponentOfType((JComponent)component, JPopupMenu.class) != null) {
          return true;
        }
      }
    }
    return false;
  }

  private boolean preprocess(final MouseEvent e, final boolean motion, JRootPane eventRootPane) {
    try {
      final MouseEvent event = convertEvent(e, eventRootPane);

      if (!IdeGlassPaneUtil.canBePreprocessed(e)) {
        return false;
      }

      for (EventListener each : mySortedMouseListeners) {
        if (motion && each instanceof MouseMotionListener) {
          fireMouseMotion((MouseMotionListener)each, event);
        }
        else if (!motion && each instanceof MouseListener) {
          fireMouseEvent((MouseListener)each, event);
        }

        if (event.isConsumed()) {
          e.consume();
          return true;
        }
      }

      return false;
    }
    finally {
      if (eventRootPane == myRootPane) {
        Cursor cursor;
        if (!myListener2Cursor.isEmpty()) {
          cursor = myListener2Cursor.values().iterator().next();

          final Point point = SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), myRootPane.getContentPane());
          Component target =
            SwingUtilities.getDeepestComponentAt(myRootPane.getContentPane().getParent(), point.x, point.y);

          if (canProcessCursorFor(target)) {
            target = getCompWithCursor(target);

            restoreLastComponent(target);

            if (target != null) {
              if (myLastCursorComponent != target) {
                myLastCursorComponent = target;
                myLastOriginalCursor = target.getCursor();
              }

              if (cursor != null && !cursor.equals(target.getCursor())) {
                target.setCursor(cursor);
              }
            }

            getRootPane().setCursor(cursor);
          }
        }
        else {
          cursor = Cursor.getDefaultCursor();
          JRootPane rootPane = getRootPane();
          if (rootPane != null) {
            rootPane.setCursor(cursor);
          } else {
            LOG.warn("Root pane is null. Event: " + e);
          }
          restoreLastComponent(null);
          myLastOriginalCursor = null;
          myLastCursorComponent = null;
        }
        myListener2Cursor.clear();
      }
    }
  }

  private boolean canProcessCursorFor(Component target) {
    if (target instanceof JMenu ||
        target instanceof JMenuItem ||
        target instanceof Divider ||
        target instanceof JSeparator ||
        (target instanceof JEditorPane && ((JEditorPane)target).getEditorKit() instanceof HTMLEditorKit)) {
      return false;
    }
    return true;
  }

  private Component getCompWithCursor(Component c) {
    Component eachParentWithCursor = c;
    while (eachParentWithCursor != null) {
      if (eachParentWithCursor.isCursorSet()) return eachParentWithCursor;
      eachParentWithCursor = eachParentWithCursor.getParent();
    }

    return null;
  }

  private void restoreLastComponent(Component newC) {
    if (myLastCursorComponent != null && myLastCursorComponent != newC) {
      myLastCursorComponent.setCursor(myLastOriginalCursor);
    }
  }


  public void setCursor(Cursor cursor, @NotNull Object requestor) {
    if (cursor == null) {
      myListener2Cursor.remove(requestor);
    }
    else {
      myListener2Cursor.put(requestor, cursor);
    }
  }

  private static MouseEvent convertEvent(final MouseEvent e, final Component target) {
    final Point point = SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), target);
    if (e instanceof MouseWheelEvent) {
      final MouseWheelEvent mwe = (MouseWheelEvent)e;
      return new MouseWheelEvent(target, mwe.getID(), mwe.getWhen(), mwe.getModifiersEx(), point.x, point.y, mwe.getClickCount(),
                                 mwe.isPopupTrigger(), mwe.getScrollType(), mwe.getScrollAmount(), mwe.getWheelRotation());
    }
    else if (e instanceof MenuDragMouseEvent) {
      final MenuDragMouseEvent de = (MenuDragMouseEvent)e;
      return new MenuDragMouseEvent(target, de.getID(), de.getWhen(), de.getModifiersEx(), point.x, point.y, e.getClickCount(),
                                    e.isPopupTrigger(), de.getPath(), de.getMenuSelectionManager());
    }
    else {
      return new MouseEvent(target, e.getID(), e.getWhen(), e.getModifiersEx(), point.x, point.y, e.getClickCount(), e.isPopupTrigger(),
                            e.getButton());
    }
  }

  private static void fireMouseEvent(final MouseListener listener, final MouseEvent event) {
    switch (event.getID()) {
      case MouseEvent.MOUSE_PRESSED:
        listener.mousePressed(event);
        break;
      case MouseEvent.MOUSE_RELEASED:
        listener.mouseReleased(event);
        break;
      case MouseEvent.MOUSE_ENTERED:
        listener.mouseEntered(event);
        break;
      case MouseEvent.MOUSE_EXITED:
        listener.mouseExited(event);
        break;
      case MouseEvent.MOUSE_CLICKED:
        listener.mouseClicked(event);
        break;
    }
  }

  private static void fireMouseMotion(MouseMotionListener listener, final MouseEvent event) {
    switch (event.getID()) {
      case MouseEvent.MOUSE_DRAGGED:
        listener.mouseDragged(event);
      case MouseEvent.MOUSE_MOVED:
        listener.mouseMoved(event);
    }
  }

  public void addMousePreprocessor(final MouseListener listener, Disposable parent) {
    _addListener(listener, parent);
  }


  public void addMouseMotionPreprocessor(final MouseMotionListener listener, final Disposable parent) {
    _addListener(listener, parent);
  }

  private void _addListener(final EventListener listener, final Disposable parent) {
    if (!myMouseListeners.contains(listener)) {
      myMouseListeners.add(listener);
      updateSortedList();
    }
    activateIfNeeded();
    Disposer.register(parent, new Disposable() {
      public void dispose() {
        UIUtil.invokeLaterIfNeeded(new Runnable() {
          public void run() {
            removeListener(listener);
          }
        });
      }
    });
  }

  public void removeMousePreprocessor(final MouseListener listener) {
    removeListener(listener);
  }

  public void removeMouseMotionPreprocessor(final MouseMotionListener listener) {
    removeListener(listener);
  }

  private void removeListener(final EventListener listener) {
    if (myMouseListeners.remove(listener)) {
      updateSortedList();
    }
    deactivateIfNeeded();
  }

  private void updateSortedList() {
    mySortedMouseListeners.clear();
    mySortedMouseListeners.addAll(myMouseListeners);
  }

  private void deactivateIfNeeded() {
    if (myPaintingActive) {
      if (myPainters.isEmpty() && getComponentCount() == 0) {
        myPaintingActive = false;
      }
    }

    if (myPreprocessorActive && myMouseListeners.isEmpty()) {
      myPreprocessorActive = false;
    }

    applyActivationState();
  }

  private void activateIfNeeded() {
    if (!myPaintingActive) {
      if (!myPainters.isEmpty() || getComponentCount() > 0) {
        myPaintingActive = true;
      }
    }

    if (!myPreprocessorActive && !myMouseListeners.isEmpty()) {
      myPreprocessorActive = true;
    }

    applyActivationState();
  }

  private void applyActivationState() {
    boolean wasVisible = isVisible();

    if (wasVisible != myPaintingActive) {
      setVisible(myPaintingActive);
    }

    IdeEventQueue queue = IdeEventQueue.getInstance();
    if (!queue.containsDispatcher(this) && (myPreprocessorActive || isVisible())) {
      queue.addDispatcher(this, null);
    }
    else if (queue.containsDispatcher(this) && !myPreprocessorActive && !isVisible()) {
      queue.removeDispatcher(this);
    }

    if (wasVisible != isVisible()) {
      revalidate();
      repaint();
    }
  }

  public void addPainter(final Component component, final Painter painter, final Disposable parent) {
    myPainters.add(painter);
    myPainter2Component.put(painter, component == null ? this : component);
    painter.addListener(this);
    activateIfNeeded();
    Disposer.register(parent, new Disposable() {
      public void dispose() {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            removePainter(painter);
          }
        });
      }
    });
  }

  public void removePainter(final Painter painter) {
    myPainters.remove(painter);
    myPainter2Component.remove(painter);
    painter.removeListener(this);
    deactivateIfNeeded();
  }


  @Override
  protected void addImpl(Component comp, Object constraints, int index) {
    super.addImpl(comp, constraints, index);

    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        activateIfNeeded();
      }
    });
  }

  @Override
  public void remove(final Component comp) {
    super.remove(comp);

    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        deactivateIfNeeded();
      }
    });
  }

  public boolean isInModalContext() {
    final Component[] components = getComponents();
    for (Component component : components) {
      if (component instanceof GlassPaneDialogWrapperPeer.TransparentLayeredPane) {
        return true;
      }
    }

    return false;
  }

  protected void paintComponent(final Graphics g) {
    if (myPainters.isEmpty()) return;

    Graphics2D g2d = (Graphics2D)g;
    for (Painter painter : myPainters) {
      final Rectangle clip = g.getClipBounds();

      final Component component = myPainter2Component.get(painter);
      if (component.getParent() == null) continue;
      final Rectangle componentBounds = SwingUtilities.convertRectangle(component.getParent(), component.getBounds(), this);

      if (!painter.needsRepaint()) {
        continue;
      }

      if (clip.contains(componentBounds) || clip.intersects(componentBounds)) {
        final Point targetPoint = SwingUtilities.convertPoint(this, 0, 0, component);
        final Rectangle targetRect = new Rectangle(targetPoint, component.getSize());
        g2d.translate(-targetRect.x, -targetRect.y);
        painter.paint(component, g2d);
        g2d.translate(targetRect.x, targetRect.y);
      }
    }
  }

  @Override
  protected void paintChildren(Graphics g) {
    super.paintChildren(g);
  }

  public boolean hasPainters() {
    return !myPainters.isEmpty();
  }

  public void onNeedsRepaint(final Painter painter, final JComponent dirtyComponent) {
    if (dirtyComponent != null && dirtyComponent.isShowing()) {
      final Rectangle rec = SwingUtilities.convertRectangle(dirtyComponent, dirtyComponent.getBounds(), this);
      if (rec != null) {
        repaint(rec);
        return;
      }
    }

    repaint();
  }

  public Component getTargetComponentFor(MouseEvent e) {
    Component candidate = findComponent(e, myRootPane.getLayeredPane());
    if (candidate != null) return candidate;
    candidate = findComponent(e, myRootPane.getContentPane());
    if (candidate != null) return candidate;
    return e.getComponent();
  }

  private static Component findComponent(final MouseEvent e, final Container container) {
    final Point lpPoint = SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), container);
    return SwingUtilities.getDeepestComponentAt(container, lpPoint.x, lpPoint.y);
  }

  @Override
  public boolean isOptimizedDrawingEnabled() {
    return !hasPainters() && super.isOptimizedDrawingEnabled();
  }

  @Override
  public JComponent getProxyComponent() {
    return myFocusProxy;
  }
}
