/*
 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.apple.laf;

import java.awt.*;
import java.awt.event.*;
import java.awt.peer.MenuComponentPeer;
import java.util.Hashtable;

import javax.swing.*;

import sun.awt.SunToolkit;
import sun.lwawt.LWToolkit;
import sun.lwawt.macosx.*;

final class ScreenMenu extends Menu
        implements ContainerListener, ComponentListener,
                   ScreenMenuPropertyHandler {

    static {
        java.security.AccessController.doPrivileged(
            new java.security.PrivilegedAction<Void>() {
                public Void run() {
                    System.loadLibrary("awt");
                    return null;
                }
            });
    }

    // screen menu stuff
    private static native long addMenuListeners(ScreenMenu listener, long nativeMenu);
    private static native void removeMenuListeners(long modelPtr);

    private transient long fModelPtr;

    private final Hashtable<Component, MenuItem> fItems;
    private final JMenu fInvoker;

    private Component fLastMouseEventTarget;
    private Rectangle fLastTargetRect;
    private volatile Rectangle[] fItemBounds;

    private ScreenMenuPropertyListener fPropertyListener;

    // Array of child hashes used to see if we need to recreate the Menu.
    private int childHashArray[];

    ScreenMenu(final JMenu invoker) {
        super(invoker.getText());
        fInvoker = invoker;

        int count = fInvoker.getMenuComponentCount();
        if (count < 5) count = 5;
        fItems = new Hashtable<Component, MenuItem>(count);
        setEnabled(fInvoker.isEnabled());
        updateItems();
    }

    /**
     * Determine if we need to tear down the Menu and re-create it, since the contents may have changed in the Menu opened listener and
     * we do not get notified of it, because EDT is busy in our code. We only need to update if the menu contents have changed in some
     * way, such as the number of menu items, the text of the menuitems, icon, shortcut etc.
     */
    private static boolean needsUpdate(final Component items[], final int childHashArray[]) {
      if (items == null || childHashArray == null) {
        return true;
      }
      if (childHashArray.length != items.length) {
       return true;
      }
      for (int i = 0; i < items.length; i++) {
          final int hashCode = getHashCode(items[i]);
          if (hashCode != childHashArray[i]) {
            return true;
          }
      }
      return false;
    }

    /**
     * Used to recreate the AWT based Menu structure that implements the Screen Menu.
     * Also computes hashcode and stores them so that we can compare them later in needsUpdate.
     */
    private void updateItems() {
        final int count = fInvoker.getMenuComponentCount();
        final Component[] items = fInvoker.getMenuComponents();
        if (needsUpdate(items, childHashArray)) {
            removeAll();
            fItems.clear();
            if (count <= 0) return;

            childHashArray = new int[count];
            for (int i = 0; i < count; i++) {
                addItem(items[i]);
                childHashArray[i] = getHashCode(items[i]);
            }
        }
    }

    /**
     * Callback from JavaMenuUpdater.m -- called when menu first opens
     */
    public void invokeOpenLater() {
        final JMenu invoker = fInvoker;
        if (invoker == null) {
            System.err.println("invoker is null!");
            return;
        }

        try {
            LWCToolkit.invokeAndWait(new Runnable() {
                public void run() {
                    invoker.setSelected(true);
                    invoker.validate();
                    updateItems();
                    fItemBounds = new Rectangle[invoker.getMenuComponentCount()];
                }
            }, invoker);
        } catch (final Exception e) {
            System.err.println(e);
            e.printStackTrace();
        }
    }

    /**
     * Callback from JavaMenuUpdater.m -- called when menu closes.
     */
    public void invokeMenuClosing() {
        final JMenu invoker = fInvoker;
        if (invoker == null) return;

        try {
            LWCToolkit.invokeAndWait(new Runnable() {
                public void run() {
                    invoker.setSelected(false);
                    // Null out the tracking rectangles and the array.
                    if (fItemBounds != null) {
                        for (int i = 0; i < fItemBounds.length; i++) {
                            fItemBounds[i] = null;
                        }
                    }
                    fItemBounds = null;
                }
            }, invoker);
        } catch (final Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Callback from JavaMenuUpdater.m -- called when menu item is hilighted.
     *
     * @param inWhichItem The menu item selected by the user. -1 if mouse moves off the menu.
     * @param itemRectTop
     * @param itemRectLeft
     * @param itemRectBottom
     * @param itemRectRight Tracking rectangle coordinates.
     */
    public void handleItemTargeted(final int inWhichItem, final int itemRectTop, final int itemRectLeft, final int itemRectBottom, final int itemRectRight) {
        if (fItemBounds == null || inWhichItem < 0 || inWhichItem > (fItemBounds.length - 1)) return;
        final Rectangle itemRect = new Rectangle(itemRectLeft, itemRectTop, itemRectRight - itemRectLeft, itemRectBottom - itemRectTop);
        fItemBounds[inWhichItem] = itemRect;
    }

    /**
     * Callback from JavaMenuUpdater.m -- called when mouse event happens on the menu.
     */
    public void handleMouseEvent(final int kind, final int x, final int y, final int modifiers, final long when) {
        if (kind == 0) return;
        if (fItemBounds == null) return;

        SunToolkit.executeOnEventHandlerThread(fInvoker, new Runnable() {
            @Override
            public void run() {
                Component target = null;
                Rectangle targetRect = null;
                for (int i = 0; i < fItemBounds.length; i++) {
                    final Rectangle testRect = fItemBounds[i];
                    if (testRect != null) {
                        if (testRect.contains(x, y)) {
                            target = fInvoker.getMenuComponent(i);
                            targetRect = testRect;
                            break;
                        }
                    }
                }
                if (target == null && fLastMouseEventTarget == null) return;

                // Send a mouseExited to the previously hilited item, if it wasn't 0.
                if (target != fLastMouseEventTarget) {
                    if (fLastMouseEventTarget != null) {
                        LWToolkit.postEvent(new MouseEvent(fLastMouseEventTarget, MouseEvent.MOUSE_EXITED, when, modifiers, x - fLastTargetRect.x, y - fLastTargetRect.y, 0, false));
                    }
                    // Send a mouseEntered to the current hilited item, if it wasn't 0.
                    if (target != null) {
                        LWToolkit.postEvent(new MouseEvent(target, MouseEvent.MOUSE_ENTERED, when, modifiers, x - targetRect.x, y - targetRect.y, 0, false));
                    }
                    fLastMouseEventTarget = target;
                    fLastTargetRect = targetRect;
                }
                // Post a mouse event to the current item.
                if (target == null) return;
                LWToolkit.postEvent(new MouseEvent(target, kind, when, modifiers, x - targetRect.x, y - targetRect.y, 0, false));
            }
        });
    }

    @Override
    public void addNotify() {
        synchronized (getTreeLock()) {
            super.addNotify();
            if (fModelPtr == 0) {
                fInvoker.getPopupMenu().addContainerListener(this);
                fInvoker.addComponentListener(this);
                fPropertyListener = new ScreenMenuPropertyListener(this);
                fInvoker.addPropertyChangeListener(fPropertyListener);

                final Icon icon = fInvoker.getIcon();
                if (icon != null) {
                    setIcon(icon);
                }

                final String tooltipText = fInvoker.getToolTipText();
                if (tooltipText != null) {
                    setToolTipText(tooltipText);
                }
                final MenuComponentPeer peer = getPeer();
                if (peer instanceof CMenu) {
                    final CMenu menu = (CMenu) peer;
                    final long nativeMenu = menu.getNativeMenu();
                    fModelPtr = addMenuListeners(this, nativeMenu);
                }
            }
        }
    }

    @Override
    public void removeNotify() {
        synchronized (getTreeLock()) {
            // Call super so that the NSMenu has been removed, before we release
            // the delegate in removeMenuListeners
            super.removeNotify();
            fItems.clear();
            if (fModelPtr != 0) {
                removeMenuListeners(fModelPtr);
                fModelPtr = 0;
                fInvoker.getPopupMenu().removeContainerListener(this);
                fInvoker.removeComponentListener(this);
                fInvoker.removePropertyChangeListener(fPropertyListener);
            }
        }
    }

    /**
     * Invoked when a component has been added to the container.
     */
    @Override
    public void componentAdded(final ContainerEvent e) {
        addItem(e.getChild());
    }

    /**
     * Invoked when a component has been removed from the container.
     */
    @Override
    public void componentRemoved(final ContainerEvent e) {
        final Component child = e.getChild();
        final MenuItem sm = fItems.remove(child);
        if (sm == null) return;

        remove(sm);
    }

    /**
     * Invoked when the component's size changes.
     */
    @Override
    public void componentResized(final ComponentEvent e) {}

    /**
     * Invoked when the component's position changes.
     */
    @Override
    public void componentMoved(final ComponentEvent e) {}

    /**
     * Invoked when the component has been made visible.
     * See componentHidden - we should still have a MenuItem
     * it just isn't inserted
     */
    @Override
    public void componentShown(final ComponentEvent e) {
        setVisible(true);
    }

    /**
     * Invoked when the component has been made invisible.
     * MenuComponent.setVisible does nothing,
     * so we remove the ScreenMenuItem from the ScreenMenu
     * but leave it in fItems
     */
    @Override
    public void componentHidden(final ComponentEvent e) {
        setVisible(false);
    }

    private void setVisible(final boolean b) {
        // Tell our parent to add/remove us
        final MenuContainer parent = getParent();

        if (parent != null) {
            if (parent instanceof ScreenMenu) {
                final ScreenMenu sm = (ScreenMenu)parent;
                sm.setChildVisible(fInvoker, b);
            }
        }
    }

    @Override
    public void setChildVisible(final JMenuItem child, final boolean b) {
        fItems.remove(child);
        updateItems();
    }

    @Override
    public void setAccelerator(final KeyStroke ks) {}

    // only check and radio items can be indeterminate
    @Override
    public void setIndeterminate(boolean indeterminate) { }

    @Override
    public void setToolTipText(final String text) {
        final MenuComponentPeer peer = getPeer();
        if (!(peer instanceof CMenuItem)) return;

        final CMenuItem cmi = (CMenuItem)peer;
        cmi.setToolTipText(text);
    }

    @Override
    public void setIcon(final Icon i) {
        final MenuComponentPeer peer = getPeer();
        if (!(peer instanceof CMenuItem)) return;

        final CMenuItem cmi = (CMenuItem)peer;
        Image img = null;

        if (i != null) {
            if (i.getIconWidth() > 0 && i.getIconHeight() > 0) {
                img = AquaIcon.getImageForIcon(i);
            }
        }
        cmi.setImage(img);
    }


    /**
     * Gets a hashCode for a JMenu or JMenuItem or subclass so that we can compare for
     * changes in the Menu.
     */
    private static int getHashCode(final Component m) {
        int hashCode = m.hashCode();

        if (m instanceof JMenuItem) {
            final JMenuItem mi = (JMenuItem) m;

            final String text = mi.getText();
            if (text != null) hashCode ^= text.hashCode();

            final Icon icon = mi.getIcon();
            if (icon != null) hashCode ^= icon.hashCode();

            final Icon disabledIcon = mi.getDisabledIcon();
            if (disabledIcon != null) hashCode ^= disabledIcon.hashCode();

            final Action action = mi.getAction();
            if (action != null) hashCode ^= action.hashCode();

            final KeyStroke ks = mi.getAccelerator();
            if (ks != null) hashCode ^= ks.hashCode();

            hashCode ^= Boolean.valueOf(mi.isVisible()).hashCode();
            hashCode ^= Boolean.valueOf(mi.isEnabled()).hashCode();
            hashCode ^= Boolean.valueOf(mi.isSelected()).hashCode();

        } else if (m instanceof JSeparator) {
            hashCode ^= "-".hashCode();
        }

        return hashCode;
    }

    private void addItem(final Component m) {
        if (!m.isVisible()) return;
        MenuItem sm = fItems.get(m);

        if (sm == null) {
            if (m instanceof JMenu) {
                sm = new ScreenMenu((JMenu)m);
            } else if (m instanceof JCheckBoxMenuItem) {
                sm = new ScreenMenuItemCheckbox((JCheckBoxMenuItem)m);
            } else if (m instanceof JRadioButtonMenuItem) {
                sm = new ScreenMenuItemCheckbox((JRadioButtonMenuItem)m);
            } else if (m instanceof JMenuItem) {
                sm = new ScreenMenuItem((JMenuItem)m);
            } else if (m instanceof JPopupMenu.Separator || m instanceof JSeparator) {
                sm = new MenuItem("-"); // This is what java.awt.Menu.addSeparator does
            }

            // Only place the menu item in the hashtable if we just created it.
            if (sm != null) {
                fItems.put(m, sm);
            }
        }

        if (sm != null) {
            add(sm);
        }
    }
}
