/*
 * Copyright (c) 2011, 2016, 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 sun.lwawt.macosx;

import sun.awt.AWTAccessor;
import sun.awt.SunToolkit;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.awt.peer.TrayIconPeer;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import static sun.awt.AWTAccessor.*;

public class CTrayIcon extends CFRetainedResource implements TrayIconPeer {
    private TrayIcon target;
    private PopupMenu popup;
    private JDialog messageDialog;
    private DialogEventHandler handler;

    // In order to construct MouseEvent object, we need to specify a
    // Component target. Because TrayIcon isn't Component's subclass,
    // we use this dummy frame instead
    private final Frame dummyFrame;

    // A bitmask that indicates what mouse buttons produce MOUSE_CLICKED events
    // on MOUSE_RELEASE. Click events are only generated if there were no drag
    // events between MOUSE_PRESSED and MOUSE_RELEASED for particular button
    private static int mouseClickButtons = 0;

    CTrayIcon(TrayIcon target) {
        super(0, true);

        this.messageDialog = null;
        this.handler = null;
        this.target = target;
        this.popup = target.getPopupMenu();
        this.dummyFrame = new Frame();
        setPtr(createModel());

        //if no one else is creating the peer.
        checkAndCreatePopupPeer();
        updateImage();
    }

    private CPopupMenu checkAndCreatePopupPeer() {
        CPopupMenu menuPeer = null;
        if (popup != null) {
            try {
                final MenuComponentAccessor acc = getMenuComponentAccessor();
                menuPeer = acc.getPeer(popup);
                if (menuPeer == null) {
                    popup.addNotify();
                    menuPeer = acc.getPeer(popup);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return menuPeer;
    }

    private long createModel() {
        return nativeCreate();
    }

    private long getModel() {
        return ptr;
    }

    private native long nativeCreate();

    //invocation from the AWTTrayIcon.m
    public long getPopupMenuModel() {
        PopupMenu newPopup = target.getPopupMenu();

        if (popup == newPopup) {
            if (popup == null) {
                return 0L;
            }
        } else {
            if (newPopup != null) {
                if (popup != null) {
                    popup.removeNotify();
                    popup = newPopup;
                } else {
                    popup = newPopup;
                }
            } else {
                return 0L;
            }
        }

        // This method is executed on Appkit, so if ptr is not zero means that,
        // it is still not deallocated(even if we call NSApp postRunnableEvent)
        // and sent CFRelease to the native queue
        return checkAndCreatePopupPeer().ptr;
    }

    /**
     * We display tray icon message as a small dialog with OK button.
     * This is lame, but JDK 1.6 does basically the same. There is a new
     * kind of window in Lion, NSPopover, so perhaps it could be used it
     * to implement better looking notifications.
     */
    public void displayMessage(final String caption, final String text,
                               final String messageType) {

        if (SwingUtilities.isEventDispatchThread()) {
            displayMessageOnEDT(caption, text, messageType);
        } else {
            try {
                SwingUtilities.invokeAndWait(new Runnable() {
                    public void run() {
                        displayMessageOnEDT(caption, text, messageType);
                    }
                });
            } catch (Exception e) {
                throw new AssertionError(e);
            }
        }
    }

    @Override
    public void dispose() {
        if (messageDialog != null) {
            disposeMessageDialog();
        }

        dummyFrame.dispose();

        if (popup != null) {
            popup.removeNotify();
        }

        LWCToolkit.targetDisposedPeer(target, this);
        target = null;

        super.dispose();
    }

    @Override
    public void setToolTip(String tooltip) {
        nativeSetToolTip(getModel(), tooltip);
    }

    //adds tooltip to the NSStatusBar's NSButton.
    private native void nativeSetToolTip(long trayIconModel, String tooltip);

    @Override
    public void showPopupMenu(int x, int y) {
        //Not used. The popupmenu is shown from the native code.
    }

    @Override
    public void updateImage() {
        Image image = target.getImage();
        if (image == null) return;

        MediaTracker tracker = new MediaTracker(new Button(""));
        tracker.addImage(image, 0);
        try {
            tracker.waitForAll();
        } catch (InterruptedException ignore) { }

        if (image.getWidth(null) <= 0 ||
            image.getHeight(null) <= 0)
        {
            return;
        }

        CImage cimage = CImage.getCreator().createFromImage(image);
        setNativeImage(getModel(), cimage.ptr, target.isImageAutoSize());
    }

    private native void setNativeImage(final long model, final long nsimage, final boolean autosize);

    private void postEvent(final AWTEvent event) {
        SunToolkit.executeOnEventHandlerThread(target, new Runnable() {
            public void run() {
                SunToolkit.postEvent(SunToolkit.targetToAppContext(target), event);
            }
        });
    }

    //invocation from the AWTTrayIcon.m
    private void handleMouseEvent(NSEvent nsEvent) {
        int buttonNumber = nsEvent.getButtonNumber();
        final SunToolkit tk = (SunToolkit)Toolkit.getDefaultToolkit();
        if ((buttonNumber > 2 && !tk.areExtraMouseButtonsEnabled())
                || buttonNumber > tk.getNumberOfButtons() - 1) {
            return;
        }

        int jeventType = NSEvent.nsToJavaEventType(nsEvent.getType());

        int jbuttonNumber = MouseEvent.NOBUTTON;
        int jclickCount = 0;
        if (jeventType != MouseEvent.MOUSE_MOVED) {
            jbuttonNumber = NSEvent.nsToJavaButton(buttonNumber);
            jclickCount = nsEvent.getClickCount();
        }

        int jmodifiers = NSEvent.nsToJavaModifiers(
                nsEvent.getModifierFlags());
        boolean isPopupTrigger = NSEvent.isPopupTrigger(jmodifiers);

        int eventButtonMask = (jbuttonNumber > 0)?
                MouseEvent.getMaskForButton(jbuttonNumber) : 0;
        long when = System.currentTimeMillis();

        if (jeventType == MouseEvent.MOUSE_PRESSED) {
            mouseClickButtons |= eventButtonMask;
        } else if (jeventType == MouseEvent.MOUSE_DRAGGED) {
            mouseClickButtons = 0;
        }

        // The MouseEvent's coordinates are relative to screen
        int absX = nsEvent.getAbsX();
        int absY = nsEvent.getAbsY();

        MouseEvent mouseEvent = new MouseEvent(dummyFrame, jeventType, when,
                jmodifiers, absX, absY, absX, absY, jclickCount, isPopupTrigger,
                jbuttonNumber);
        mouseEvent.setSource(target);
        postEvent(mouseEvent);

        // fire ACTION event
        if (jeventType == MouseEvent.MOUSE_PRESSED && isPopupTrigger) {
            final String cmd = target.getActionCommand();
            final ActionEvent event = new ActionEvent(target,
                    ActionEvent.ACTION_PERFORMED, cmd);
            postEvent(event);
        }

        // synthesize CLICKED event
        if (jeventType == MouseEvent.MOUSE_RELEASED) {
            if ((mouseClickButtons & eventButtonMask) != 0) {
                MouseEvent clickEvent = new MouseEvent(dummyFrame,
                        MouseEvent.MOUSE_CLICKED, when, jmodifiers, absX, absY,
                        absX, absY, jclickCount, isPopupTrigger, jbuttonNumber);
                clickEvent.setSource(target);
                postEvent(clickEvent);
            }

            mouseClickButtons &= ~eventButtonMask;
        }
    }

    private native Point2D nativeGetIconLocation(long trayIconModel);

    public void displayMessageOnEDT(String caption, String text,
                                    String messageType) {
        if (messageDialog != null) {
            disposeMessageDialog();
        }

        // obtain icon to show along the message
        Icon icon = getIconForMessageType(messageType);
        if (icon != null) {
            icon = new ImageIcon(scaleIcon(icon, 0.75));
        }

        // We want the message dialog text area to be about 1/8 of the screen
        // size. There is nothing special about this value, it's just makes the
        // message dialog to look nice
        Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        int textWidth = screenSize.width / 8;

        // create dialog to show
        messageDialog = createMessageDialog(caption, text, textWidth, icon);

        // finally, show the dialog to user
        showMessageDialog();
    }

    /**
     * Creates dialog window used to display the message
     */
    private JDialog createMessageDialog(String caption, String text,
                                     int textWidth, Icon icon) {
        JDialog dialog;
        handler = new DialogEventHandler();

        JTextArea captionArea = null;
        if (caption != null) {
            captionArea = createTextArea(caption, textWidth, false, true);
        }

        JTextArea textArea = null;
        if (text != null){
            textArea = createTextArea(text, textWidth, true, false);
        }

        Object[] panels = null;
        if (captionArea != null) {
            if (textArea != null) {
                panels = new Object[] {captionArea, new JLabel(), textArea};
            } else {
                panels = new Object[] {captionArea};
            }
        } else {
           if (textArea != null) {
                panels = new Object[] {textArea};
            }
        }

        // We want message dialog with small title bar. There is a client
        // property property that does it, however, it must be set before
        // dialog's native window is created. This is why we create option
        // pane and dialog separately
        final JOptionPane op = new JOptionPane(panels);
        op.setIcon(icon);
        op.addPropertyChangeListener(handler);

        // Make Ok button small. Most likely won't work for L&F other then Aqua
        try {
            JPanel buttonPanel = (JPanel)op.getComponent(1);
            JButton ok = (JButton)buttonPanel.getComponent(0);
            ok.putClientProperty("JComponent.sizeVariant", "small");
        } catch (Throwable t) {
            // do nothing, we tried and failed, no big deal
        }

        dialog = new JDialog((Dialog) null);
        JRootPane rp = dialog.getRootPane();

        // gives us dialog window with small title bar and not zoomable
        rp.putClientProperty(CPlatformWindow.WINDOW_STYLE, "small");
        rp.putClientProperty(CPlatformWindow.WINDOW_ZOOMABLE, "false");

        dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
        dialog.setModal(false);
        dialog.setModalExclusionType(Dialog.ModalExclusionType.TOOLKIT_EXCLUDE);
        dialog.setAlwaysOnTop(true);
        dialog.setAutoRequestFocus(false);
        dialog.setResizable(false);
        dialog.setContentPane(op);

        dialog.addWindowListener(handler);

        // suppress security warning for untrusted windows
        AWTAccessor.getWindowAccessor().setTrayIconWindow(dialog, true);

        dialog.pack();

        return dialog;
    }

    private void showMessageDialog() {

        Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        Point2D iconLoc = nativeGetIconLocation(getModel());

        int dialogY = (int)iconLoc.getY();
        int dialogX = (int)iconLoc.getX();
        if (dialogX + messageDialog.getWidth() > screenSize.width) {
            dialogX = screenSize.width - messageDialog.getWidth();
        }

        messageDialog.setLocation(dialogX, dialogY);
        messageDialog.setVisible(true);
    }

   private void disposeMessageDialog() {
        if (SwingUtilities.isEventDispatchThread()) {
            disposeMessageDialogOnEDT();
        } else {
            try {
                SwingUtilities.invokeAndWait(new Runnable() {
                    public void run() {
                        disposeMessageDialogOnEDT();
                    }
                });
            } catch (Exception e) {
                throw new AssertionError(e);
            }
        }
   }

    private void disposeMessageDialogOnEDT() {
        if (messageDialog != null) {
            messageDialog.removeWindowListener(handler);
            messageDialog.removePropertyChangeListener(handler);
            messageDialog.dispose();

            messageDialog = null;
            handler = null;
        }
    }

    /**
     * Scales an icon using specified scale factor
     *
     * @param icon        icon to scale
     * @param scaleFactor scale factor to use
     * @return scaled icon as BuffedredImage
     */
    private static BufferedImage scaleIcon(Icon icon, double scaleFactor) {
        if (icon == null) {
            return null;
        }

        int w = icon.getIconWidth();
        int h = icon.getIconHeight();

        GraphicsEnvironment ge =
                GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice gd = ge.getDefaultScreenDevice();
        GraphicsConfiguration gc = gd.getDefaultConfiguration();

        // convert icon into image
        BufferedImage iconImage = gc.createCompatibleImage(w, h,
                Transparency.TRANSLUCENT);
        Graphics2D g = iconImage.createGraphics();
        icon.paintIcon(null, g, 0, 0);
        g.dispose();

        // and scale it nicely
        int scaledW = (int) (w * scaleFactor);
        int scaledH = (int) (h * scaleFactor);
        BufferedImage scaledImage = gc.createCompatibleImage(scaledW, scaledH,
                Transparency.TRANSLUCENT);
        g = scaledImage.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.drawImage(iconImage, 0, 0, scaledW, scaledH, null);
        g.dispose();

        return scaledImage;
    }


    /**
     * Gets Aqua icon used in message dialog.
     */
    private static Icon getIconForMessageType(String messageType) {
        if (messageType.equals("ERROR")) {
            return UIManager.getIcon("OptionPane.errorIcon");
        } else if (messageType.equals("WARNING")) {
            return UIManager.getIcon("OptionPane.warningIcon");
        } else {
            // this is just an application icon
            return UIManager.getIcon("OptionPane.informationIcon");
        }
    }

    private static JTextArea createTextArea(String text, int width,
                                            boolean isSmall, boolean isBold) {
        JTextArea textArea = new JTextArea(text);

        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        textArea.setEditable(false);
        textArea.setFocusable(false);
        textArea.setBorder(null);
        textArea.setBackground(new JLabel().getBackground());

        if (isSmall) {
            textArea.putClientProperty("JComponent.sizeVariant", "small");
        }

        if (isBold) {
            Font font = textArea.getFont();
            Font boldFont = new Font(font.getName(), Font.BOLD, font.getSize());
            textArea.setFont(boldFont);
        }

        textArea.setSize(width, 1);

        return textArea;
    }

    /**
     * Implements all the Listeners needed by message dialog
     */
    private final class DialogEventHandler extends WindowAdapter
            implements PropertyChangeListener {

        public void windowClosing(WindowEvent we) {
                disposeMessageDialog();
        }

        public void propertyChange(PropertyChangeEvent e) {
            if (messageDialog == null) {
                return;
            }

            String prop = e.getPropertyName();
            Container cp = messageDialog.getContentPane();

            if (messageDialog.isVisible() && e.getSource() == cp &&
                    (prop.equals(JOptionPane.VALUE_PROPERTY))) {
                disposeMessageDialog();
            }
        }
    }
}

