/*
 * Copyright (c) 1996, 2009, 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.awt;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.peer.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.lang.reflect.Field;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.util.Set;
import java.awt.AWTKeyStroke;
import java.applet.Applet;
import sun.applet.AppletPanel;

/**
 * A generic container used for embedding Java components, usually applets.
 * An EmbeddedFrame has two related uses:
 *
 * . Within a Java-based application, an EmbeddedFrame serves as a sort of
 *   firewall, preventing the contained components or applets from using
 *   getParent() to find parent components, such as menubars.
 *
 * . Within a C-based application, an EmbeddedFrame contains a window handle
 *   which was created by the application, which serves as the top-level
 *   Java window.  EmbeddedFrames created for this purpose are passed-in a
 *   handle of an existing window created by the application.  The window
 *   handle should be of the appropriate native type for a specific
 *   platform, as stored in the pData field of the ComponentPeer.
 *
 * @author      Thomas Ball
 */
public abstract class EmbeddedFrame extends Frame
                          implements KeyEventDispatcher, PropertyChangeListener {

    private boolean isCursorAllowed = true;
    private static Field fieldPeer;
    private static Field currentCycleRoot;
    private boolean supportsXEmbed = false;
    private KeyboardFocusManager appletKFM;
    // JDK 1.1 compatibility
    private static final long serialVersionUID = 2967042741780317130L;

    // Use these in traverseOut method to determine directions
    protected static final boolean FORWARD = true;
    protected static final boolean BACKWARD = false;

    public boolean supportsXEmbed() {
        return supportsXEmbed && SunToolkit.needsXEmbed();
    }

    protected EmbeddedFrame(boolean supportsXEmbed) {
        this((long)0, supportsXEmbed);
    }


    protected EmbeddedFrame() {
        this((long)0);
    }

    /**
     * @deprecated This constructor will be removed in 1.5
     */
    @Deprecated
    protected EmbeddedFrame(int handle) {
        this((long)handle);
    }

    protected EmbeddedFrame(long handle) {
        this(handle, false);
    }

    protected EmbeddedFrame(long handle, boolean supportsXEmbed) {
        this.supportsXEmbed = supportsXEmbed;
        registerListeners();
    }

    /**
     * Block introspection of a parent window by this child.
     */
    public Container getParent() {
        return null;
    }

    /**
     * Needed to track which KeyboardFocusManager is current. We want to avoid memory
     * leaks, so when KFM stops being current, we remove ourselves as listeners.
     */
    public void propertyChange(PropertyChangeEvent evt) {
        // We don't handle any other properties. Skip it.
        if (!evt.getPropertyName().equals("managingFocus")) {
            return;
        }

        // We only do it if it stops being current. Technically, we should
        // never get an event about KFM starting being current.
        if (evt.getNewValue() == Boolean.TRUE) {
            return;
        }

        // should be the same as appletKFM
        removeTraversingOutListeners((KeyboardFocusManager)evt.getSource());

        appletKFM = KeyboardFocusManager.getCurrentKeyboardFocusManager();
        if (isVisible()) {
            addTraversingOutListeners(appletKFM);
        }
    }

    /**
     * Register us as KeyEventDispatcher and property "managingFocus" listeners.
     */
    private void addTraversingOutListeners(KeyboardFocusManager kfm) {
        kfm.addKeyEventDispatcher(this);
        kfm.addPropertyChangeListener("managingFocus", this);
    }

    /**
     * Deregister us as KeyEventDispatcher and property "managingFocus" listeners.
     */
    private void removeTraversingOutListeners(KeyboardFocusManager kfm) {
        kfm.removeKeyEventDispatcher(this);
        kfm.removePropertyChangeListener("managingFocus", this);
    }

    /**
     * Because there may be many AppContexts, and we can't be sure where this
     * EmbeddedFrame is first created or shown, we can't automatically determine
     * the correct KeyboardFocusManager to attach to as KeyEventDispatcher.
     * Those who want to use the functionality of traversing out of the EmbeddedFrame
     * must call this method on the Applet's AppContext. After that, all the changes
     * can be handled automatically, including possible replacement of
     * KeyboardFocusManager.
     */
    public void registerListeners() {
        if (appletKFM != null) {
            removeTraversingOutListeners(appletKFM);
        }
        appletKFM = KeyboardFocusManager.getCurrentKeyboardFocusManager();
        if (isVisible()) {
            addTraversingOutListeners(appletKFM);
        }
    }

    /**
     * Needed to avoid memory leak: we register this EmbeddedFrame as a listener with
     * KeyboardFocusManager of applet's AppContext. We don't want the KFM to keep
     * reference to our EmbeddedFrame forever if the Frame is no longer in use, so we
     * add listeners in show() and remove them in hide().
     */
    public void show() {
        if (appletKFM != null) {
            addTraversingOutListeners(appletKFM);
        }
        super.show();
    }

    /**
     * Needed to avoid memory leak: we register this EmbeddedFrame as a listener with
     * KeyboardFocusManager of applet's AppContext. We don't want the KFM to keep
     * reference to our EmbeddedFrame forever if the Frame is no longer in use, so we
     * add listeners in show() and remove them in hide().
     */
    public void hide() {
        if (appletKFM != null) {
            removeTraversingOutListeners(appletKFM);
        }
        super.hide();
    }

    /**
     * Need this method to detect when the focus may have chance to leave the
     * focus cycle root which is EmbeddedFrame. Mostly, the code here is copied
     * from DefaultKeyboardFocusManager.processKeyEvent with some minor
     * modifications.
     */
    public boolean dispatchKeyEvent(KeyEvent e) {

        // We can't guarantee that this is called on the same AppContext as EmbeddedFrame
        // belongs to. That's why we can't use public methods to find current focus cycle
        // root. Instead, we access KFM's private field directly.
        if (currentCycleRoot == null) {
            currentCycleRoot = (Field)AccessController.doPrivileged(new PrivilegedAction() {
                public Object run() {
                    try {
                        Field unaccessibleRoot = KeyboardFocusManager.class.
                                                     getDeclaredField("currentFocusCycleRoot");
                        if (unaccessibleRoot != null) {
                            unaccessibleRoot.setAccessible(true);
                        }
                        return unaccessibleRoot;
                    } catch (NoSuchFieldException e1) {
                        assert false;
                    } catch (SecurityException e2) {
                        assert false;
                    }
                    return null;
                }
            });
        }

        Container currentRoot = null;
        if (currentCycleRoot != null) {
            try {
                // The field is static, so we can pass null to Field.get() as the argument.
                currentRoot = (Container)currentCycleRoot.get(null);
            } catch (IllegalAccessException e3) {
                // This is impossible: currentCycleRoot would be null if setAccessible failed.
                assert false;
            }
        }

        // if we are not in EmbeddedFrame's cycle, we should not try to leave.
        if (this != currentRoot) {
            return false;
        }

        // KEY_TYPED events cannot be focus traversal keys
        if (e.getID() == KeyEvent.KEY_TYPED) {
            return false;
        }

        if (!getFocusTraversalKeysEnabled() || e.isConsumed()) {
            return false;
        }

        AWTKeyStroke stroke = AWTKeyStroke.getAWTKeyStrokeForEvent(e);
        Set toTest;
        Component currentFocused = e.getComponent();

        toTest = getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
        if (toTest.contains(stroke)) {
            // 6581899: performance improvement for SortingFocusTraversalPolicy
            Component last = getFocusTraversalPolicy().getLastComponent(this);
            if (currentFocused == last || last == null) {
                if (traverseOut(FORWARD)) {
                    e.consume();
                    return true;
                }
            }
        }

        toTest = getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
        if (toTest.contains(stroke)) {
            // 6581899: performance improvement for SortingFocusTraversalPolicy
            Component first = getFocusTraversalPolicy().getFirstComponent(this);
            if (currentFocused == first || first == null) {
                if (traverseOut(BACKWARD)) {
                    e.consume();
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * This method is called from dispatchKeyEvent in the following two cases:
     * 1. The focus is on the first Component of this EmbeddedFrame and we are
     *    about to transfer the focus backward.
     * 2. The focus in on the last Component of this EmbeddedFrame and we are
     *    about to transfer the focus forward.
     * This is needed to give the opportuity for keyboard focus to leave the
     * EmbeddedFrame. Override this method, initiate focus transfer in it and
     * return true if you want the focus to leave EmbeddedFrame's cycle.
     * The direction parameter specifies which of the two mentioned cases is
     * happening. Use FORWARD and BACKWARD constants defined in EmbeddedFrame
     * to avoid confusing boolean values.
     *
     * @param direction FORWARD or BACKWARD
     * @return true, if EmbeddedFrame wants the focus to leave it,
     *         false otherwise.
     */
    protected boolean traverseOut(boolean direction) {
        return false;
    }

    /**
     * Block modifying any frame attributes, since they aren't applicable
     * for EmbeddedFrames.
     */
    public void setTitle(String title) {}
    public void setIconImage(Image image) {}
    public void setIconImages(java.util.List<? extends Image> icons) {}
    public void setMenuBar(MenuBar mb) {}
    public void setResizable(boolean resizable) {}
    public void remove(MenuComponent m) {}

    public boolean isResizable() {
        return true;
    }

    public void addNotify() {
        synchronized (getTreeLock()) {
            if (getPeer() == null) {
                setPeer(new NullEmbeddedFramePeer());
            }
            super.addNotify();
        }
    }

    // These three functions consitute RFE 4100710. Do not remove.
    public void setCursorAllowed(boolean isCursorAllowed) {
        this.isCursorAllowed = isCursorAllowed;
        getPeer().updateCursorImmediately();
    }
    public boolean isCursorAllowed() {
        return isCursorAllowed;
    }
    public Cursor getCursor() {
        return (isCursorAllowed)
            ? super.getCursor()
            : Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
    }

    protected  void setPeer(final ComponentPeer p){
        if (fieldPeer == null) {
            fieldPeer = (Field)AccessController.doPrivileged(new PrivilegedAction() {
                    public Object run() {
                        try {
                            Field lnkPeer = Component.class.getDeclaredField("peer");
                            if (lnkPeer != null) {
                                lnkPeer.setAccessible(true);
                            }
                            return lnkPeer;
                        } catch (NoSuchFieldException e) {
                            assert false;
                        } catch (SecurityException e) {
                            assert false;
                        }
                        return null;
                    }//run
                });
        }
        try{
            if (fieldPeer !=null){
                fieldPeer.set(EmbeddedFrame.this, p);
            }
        } catch (IllegalAccessException e) {
            assert false;
        }
    };  //setPeer method ends

    /**
     * Synthesize native message to activate or deactivate EmbeddedFrame window
     * depending on the value of parameter <code>b</code>.
     * Peers should override this method if they are to implement
     * this functionality.
     * @param doActivate  if <code>true</code>, activates the window;
     * otherwise, deactivates the window
     */
    public void synthesizeWindowActivation(boolean doActivate) {}

    /**
     * Moves this embedded frame to a new location. The top-left corner of
     * the new location is specified by the <code>x</code> and <code>y</code>
     * parameters relative to the native parent component.
     * <p>
     * setLocation() and setBounds() for EmbeddedFrame really don't move it
     * within the native parent. These methods always put embedded frame to
     * (0, 0) for backward compatibility. To allow moving embedded frame
     * setLocationPrivate() and setBoundsPrivate() were introduced, and they
     * work just the same way as setLocation() and setBounds() for usual,
     * non-embedded components.
     * </p>
     * <p>
     * Using usual get/setLocation() and get/setBounds() together with new
     * get/setLocationPrivate() and get/setBoundsPrivate() is not recommended.
     * For example, calling getBoundsPrivate() after setLocation() works fine,
     * but getBounds() after setBoundsPrivate() may return unpredictable value.
     * </p>
     * @param x the new <i>x</i>-coordinate relative to the parent component
     * @param y the new <i>y</i>-coordinate relative to the parent component
     * @see java.awt.Component#setLocation
     * @see #getLocationPrivate
     * @see #setBoundsPrivate
     * @see #getBoundsPrivate
     * @since 1.5
     */
    protected void setLocationPrivate(int x, int y) {
        Dimension size = getSize();
        setBoundsPrivate(x, y, size.width, size.height);
    }

    /**
     * Gets the location of this embedded frame as a point specifying the
     * top-left corner relative to parent component.
     * <p>
     * setLocation() and setBounds() for EmbeddedFrame really don't move it
     * within the native parent. These methods always put embedded frame to
     * (0, 0) for backward compatibility. To allow getting location and size
     * of embedded frame getLocationPrivate() and getBoundsPrivate() were
     * introduced, and they work just the same way as getLocation() and getBounds()
     * for ususal, non-embedded components.
     * </p>
     * <p>
     * Using usual get/setLocation() and get/setBounds() together with new
     * get/setLocationPrivate() and get/setBoundsPrivate() is not recommended.
     * For example, calling getBoundsPrivate() after setLocation() works fine,
     * but getBounds() after setBoundsPrivate() may return unpredictable value.
     * </p>
     * @return a point indicating this embedded frame's top-left corner
     * @see java.awt.Component#getLocation
     * @see #setLocationPrivate
     * @see #setBoundsPrivate
     * @see #getBoundsPrivate
     * @since 1.6
     */
    protected Point getLocationPrivate() {
        Rectangle bounds = getBoundsPrivate();
        return new Point(bounds.x, bounds.y);
    }

    /**
     * Moves and resizes this embedded frame. The new location of the top-left
     * corner is specified by <code>x</code> and <code>y</code> parameters
     * relative to the native parent component. The new size is specified by
     * <code>width</code> and <code>height</code>.
     * <p>
     * setLocation() and setBounds() for EmbeddedFrame really don't move it
     * within the native parent. These methods always put embedded frame to
     * (0, 0) for backward compatibility. To allow moving embedded frames
     * setLocationPrivate() and setBoundsPrivate() were introduced, and they
     * work just the same way as setLocation() and setBounds() for usual,
     * non-embedded components.
     * </p>
     * <p>
     * Using usual get/setLocation() and get/setBounds() together with new
     * get/setLocationPrivate() and get/setBoundsPrivate() is not recommended.
     * For example, calling getBoundsPrivate() after setLocation() works fine,
     * but getBounds() after setBoundsPrivate() may return unpredictable value.
     * </p>
     * @param x the new <i>x</i>-coordinate relative to the parent component
     * @param y the new <i>y</i>-coordinate relative to the parent component
     * @param width the new <code>width</code> of this embedded frame
     * @param height the new <code>height</code> of this embedded frame
     * @see java.awt.Component#setBounds
     * @see #setLocationPrivate
     * @see #getLocationPrivate
     * @see #getBoundsPrivate
     * @since 1.5
     */
    protected void setBoundsPrivate(int x, int y, int width, int height) {
        final FramePeer peer = (FramePeer)getPeer();
        if (peer != null) {
            peer.setBoundsPrivate(x, y, width, height);
        }
    }

    /**
     * Gets the bounds of this embedded frame as a rectangle specifying the
     * width, height and location relative to the native parent component.
     * <p>
     * setLocation() and setBounds() for EmbeddedFrame really don't move it
     * within the native parent. These methods always put embedded frame to
     * (0, 0) for backward compatibility. To allow getting location and size
     * of embedded frames getLocationPrivate() and getBoundsPrivate() were
     * introduced, and they work just the same way as getLocation() and getBounds()
     * for ususal, non-embedded components.
     * </p>
     * <p>
     * Using usual get/setLocation() and get/setBounds() together with new
     * get/setLocationPrivate() and get/setBoundsPrivate() is not recommended.
     * For example, calling getBoundsPrivate() after setLocation() works fine,
     * but getBounds() after setBoundsPrivate() may return unpredictable value.
     * </p>
     * @return a rectangle indicating this embedded frame's bounds
     * @see java.awt.Component#getBounds
     * @see #setLocationPrivate
     * @see #getLocationPrivate
     * @see #setBoundsPrivate
     * @since 1.6
     */
    protected Rectangle getBoundsPrivate() {
        final FramePeer peer = (FramePeer)getPeer();
        if (peer != null) {
            return peer.getBoundsPrivate();
        }
        else {
            return getBounds();
        }
    }

    public void toFront() {}
    public void toBack() {}

    public abstract void registerAccelerator(AWTKeyStroke stroke);
    public abstract void unregisterAccelerator(AWTKeyStroke stroke);

    /**
     * Checks if the component is in an EmbeddedFrame. If so,
     * returns the applet found in the hierarchy or null if
     * not found.
     * @return the parent applet or {@ null}
     * @since 1.6
     */
    public static Applet getAppletIfAncestorOf(Component comp) {
        Container parent = comp.getParent();
        Applet applet = null;
        while (parent != null && !(parent instanceof EmbeddedFrame)) {
            if (parent instanceof Applet) {
                applet = (Applet)parent;
            }
            parent = parent.getParent();
        }
        return parent == null ? null : applet;
    }

    /**
     * This method should be overriden in subclasses. It is
     * called when window this frame is within should be blocked
     * by some modal dialog.
     */
    public void notifyModalBlocked(Dialog blocker, boolean blocked) {
    }

    private static class NullEmbeddedFramePeer
        extends NullComponentPeer implements FramePeer {
        public void setTitle(String title) {}
        public void setIconImage(Image im) {}
        public void updateIconImages() {}
        public void setMenuBar(MenuBar mb) {}
        public void setResizable(boolean resizeable) {}
        public void setState(int state) {}
        public int getState() { return Frame.NORMAL; }
        public void setMaximizedBounds(Rectangle b) {}
        public void toFront() {}
        public void toBack() {}
        public void updateFocusableWindowState() {}
        public void updateAlwaysOnTop() {}
        public void setAlwaysOnTop(boolean alwaysOnTop) {}
        public Component getGlobalHeavyweightFocusOwner() { return null; }
        public void setBoundsPrivate(int x, int y, int width, int height) {
            setBounds(x, y, width, height, SET_BOUNDS);
        }
        public Rectangle getBoundsPrivate() {
            return getBounds();
        }
        public void setModalBlocked(Dialog blocker, boolean blocked) {}

        /**
         * @see java.awt.peer.ContainerPeer#restack
         */
        public void restack() {
            throw new UnsupportedOperationException();
        }

        /**
         * @see java.awt.peer.ContainerPeer#isRestackSupported
         */
        public boolean isRestackSupported() {
            return false;
        }
        public boolean requestWindowFocus() {
            return false;
        }
        public void updateMinimumSize() {
        }

        public void setOpacity(float opacity) {
        }

        public void setOpaque(boolean isOpaque) {
        }

        public void updateWindow() {
        }

        public void repositionSecurityWarning() {
        }
     }
} // class EmbeddedFrame
