/*
 * 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;

import java.awt.*;

import java.awt.dnd.DropTarget;
import java.awt.dnd.peer.DropTargetPeer;
import java.awt.event.*;

import java.awt.image.ColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.VolatileImage;

import java.awt.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;

import java.awt.peer.KeyboardFocusManagerPeer;
import java.util.concurrent.atomic.AtomicBoolean;
import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedAction;

import sun.awt.*;

import sun.awt.event.IgnorePaintEvent;

import sun.awt.image.SunVolatileImage;
import sun.awt.image.ToolkitImage;

import sun.java2d.SunGraphics2D;
import sun.java2d.opengl.OGLRenderQueue;
import sun.java2d.pipe.Region;

import sun.util.logging.PlatformLogger;

import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import javax.swing.RepaintManager;

import com.sun.java.swing.SwingUtilities3;

public abstract class LWComponentPeer<T extends Component, D extends JComponent>
    implements ComponentPeer, DropTargetPeer
{
    private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.lwawt.focus.LWComponentPeer");

    /**
     * State lock is to be used for modifications to this peer's fields (e.g.
     * bounds, background, font, etc.) It should be the last lock in the lock
     * chain
     */
    private final Object stateLock = new Object();

    /**
     * The lock to operate with the peers hierarchy. AWT tree lock is not used
     * as there are many peers related ops to be done on the toolkit thread, and
     * we don't want to depend on a public lock on this thread
     */
    private static final Object peerTreeLock = new Object();

    /**
     * The associated AWT object.
     */
    private final T target;

    /**
     * Container peer. It may not be the peer of the target's direct parent, for
     * example, in the case of hw/lw mixing. However, let's skip this scenario
     * for the time being. We also assume the container peer is not null, which
     * might also be false if addNotify() is called for a component outside of
     * the hierarchy. The exception is LWWindowPeers: their containers are
     * always null
     */
    private final LWContainerPeer<?, ?> containerPeer;

    /**
     * Handy reference to the top-level window peer. Window peer is borrowed
     * from the containerPeer in constructor, and should also be updated when
     * the component is reparented to another container
     */
    private final LWWindowPeer windowPeer;

    private final AtomicBoolean disposed = new AtomicBoolean(false);

    // Bounds are relative to parent peer
    private final Rectangle bounds = new Rectangle();
    private Region region;

    // Component state. Should be accessed under the state lock
    private boolean visible = false;
    private boolean enabled = true;

    private Color background;
    private Color foreground;
    private Font font;

    /**
     * Paint area to coalesce all the paint events and store the target dirty
     * area.
     */
    private final RepaintArea targetPaintArea;

    //   private volatile boolean paintPending;
    private volatile boolean isLayouting;

    private final D delegate;
    private Container delegateContainer;
    private Component delegateDropTarget;
    private final Object dropTargetLock = new Object();

    private int fNumDropTargets = 0;
    private PlatformDropTarget fDropTarget = null;

    private final PlatformComponent platformComponent;

    /**
     * Character with reasonable value between the minimum width and maximum.
     */
    static final char WIDE_CHAR = '0';

    /**
     * The back buffer provide user with a BufferStrategy.
     */
    private Image backBuffer;

    /**
     * All Swing delegates use delegateContainer as a parent. This container
     * intentionally do not use parent of the peer.
     */
    @SuppressWarnings("serial")// Safe: outer class is non-serializable.
    private final class DelegateContainer extends Container {
        {
            enableEvents(0xFFFFFFFF);
        }

        // Empty non private constructor was added because access to this
        // class shouldn't be emulated by a synthetic accessor method.
        DelegateContainer() {
            super();
        }

        @Override
        public boolean isLightweight() {
            return false;
        }

        @Override
        public Point getLocation() {
            return getLocationOnScreen();
        }

        @Override
        public Point getLocationOnScreen() {
            return LWComponentPeer.this.getLocationOnScreen();
        }

        @Override
        public int getX() {
            return getLocation().x;
        }

        @Override
        public int getY() {
            return getLocation().y;
        }
    }

    LWComponentPeer(final T target, final PlatformComponent platformComponent) {
        targetPaintArea = new LWRepaintArea();
        this.target = target;
        this.platformComponent = platformComponent;

        // Container peer is always null for LWWindowPeers, so
        // windowPeer is always null for them as well. On the other
        // hand, LWWindowPeer shouldn't use windowPeer at all
        final Container container = SunToolkit.getNativeContainer(target);
        containerPeer = (LWContainerPeer) LWToolkit.targetToPeer(container);
        windowPeer = containerPeer != null ? containerPeer.getWindowPeerOrSelf()
                                           : null;
        // don't bother about z-order here as updateZOrder()
        // will be called from addNotify() later anyway
        if (containerPeer != null) {
            containerPeer.addChildPeer(this);
        }

        // the delegate must be created after the target is set
        AWTEventListener toolkitListener = null;
        synchronized (Toolkit.getDefaultToolkit()) {
            try {
                toolkitListener = getToolkitAWTEventListener();
                setToolkitAWTEventListener(null);

                synchronized (getDelegateLock()) {
                    delegate = createDelegate();
                    if (delegate != null) {
                        delegate.setVisible(false);
                        delegateContainer = new DelegateContainer();
                        delegateContainer.add(delegate);
                        delegateContainer.addNotify();
                        delegate.addNotify();
                        resetColorsAndFont(delegate);
                        delegate.setOpaque(true);
                    } else {
                        return;
                    }
                }

            } finally {
                setToolkitAWTEventListener(toolkitListener);
            }

            // todo swing: later on we will probably have one global RM
            SwingUtilities3.setDelegateRepaintManager(delegate, new RepaintManager() {
                @Override
                public void addDirtyRegion(final JComponent c, final int x, final int y, final int w, final int h) {
                    repaintPeer(SwingUtilities.convertRectangle(
                            c, new Rectangle(x, y, w, h), getDelegate()));
                }
            });
        }
    }

    /**
     * This method must be called under Toolkit.getDefaultToolkit() lock
     * and followed by setToolkitAWTEventListener()
     */
    protected final AWTEventListener getToolkitAWTEventListener() {
        return AccessController.doPrivileged(new PrivilegedAction<AWTEventListener>() {
            public AWTEventListener run() {
                Toolkit toolkit = Toolkit.getDefaultToolkit();
                try {
                    Field field = Toolkit.class.getDeclaredField("eventListener");
                    field.setAccessible(true);
                    return (AWTEventListener) field.get(toolkit);
                } catch (Exception e) {
                    throw new InternalError(e.toString());
                }
            }
        });
    }

    protected final void setToolkitAWTEventListener(final AWTEventListener listener) {
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {
                Toolkit toolkit = Toolkit.getDefaultToolkit();
                try {
                    Field field = Toolkit.class.getDeclaredField("eventListener");
                    field.setAccessible(true);
                    field.set(toolkit, listener);
                } catch (Exception e) {
                    throw new InternalError(e.toString());
                }
                return null;
            }
        });
    }

    /**
     * This method is called under getDelegateLock().
     * Overridden in subclasses.
     */
    D createDelegate() {
        return null;
    }

    final D getDelegate() {
        return delegate;
    }

    /**
     * This method should be called under getDelegateLock().
     */
    Component getDelegateFocusOwner() {
        return getDelegate();
    }

    /**
     * Initializes this peer. The call to initialize() is not placed to
     * LWComponentPeer ctor to let the subclass ctor to finish completely first.
     * Instead, it's the LWToolkit object who is responsible for initialization.
     * Note that we call setVisible() at the end of initialization.
     */
    public final void initialize() {
        platformComponent.initialize(getPlatformWindow());
        initializeImpl();
        setVisible(target.isVisible());
    }

    /**
     * Fetching general properties from the target. Should be overridden in
     * subclasses to initialize specific peers properties.
     */
    void initializeImpl() {
        // note that these methods can be overridden by the user and
        // can return some strange values like null.
        setBackground(target.getBackground());
        setForeground(target.getForeground());
        setFont(target.getFont());
        setBounds(target.getBounds());
        setEnabled(target.isEnabled());
    }

    private static void resetColorsAndFont(final Container c) {
        c.setBackground(null);
        c.setForeground(null);
        c.setFont(null);
        for (int i = 0; i < c.getComponentCount(); i++) {
            resetColorsAndFont((Container) c.getComponent(i));
        }
    }

    final Object getStateLock() {
        return stateLock;
    }

    /**
     * Synchronize all operations with the Swing delegates under AWT tree lock,
     * using a new separate lock to synchronize access to delegates may lead
     * deadlocks. Think of it as a 'virtual EDT'.
     *
     * @return DelegateLock
     */
    final Object getDelegateLock() {
        return getTarget().getTreeLock();
    }

    protected static final Object getPeerTreeLock() {
        return peerTreeLock;
    }

    public final T getTarget() {
        return target;
    }

    // Just a helper method
    // Returns the window peer or null if this is a window peer
    protected final LWWindowPeer getWindowPeer() {
        return windowPeer;
    }

    // Returns the window peer or 'this' if this is a window peer
    protected LWWindowPeer getWindowPeerOrSelf() {
        return getWindowPeer();
    }

    // Just a helper method
    protected final LWContainerPeer<?, ?> getContainerPeer() {
        return containerPeer;
    }

    public PlatformWindow getPlatformWindow() {
        LWWindowPeer windowPeer = getWindowPeer();
        return windowPeer.getPlatformWindow();
    }

    // ---- PEER METHODS ---- //

    // Just a helper method
    public LWToolkit getLWToolkit() {
        return LWToolkit.getLWToolkit();
    }

    @Override
    public final void dispose() {
        if (disposed.compareAndSet(false, true)) {
            disposeImpl();
        }
    }

    protected void disposeImpl() {
        destroyBuffers();
        LWContainerPeer<?, ?> cp = getContainerPeer();
        if (cp != null) {
            cp.removeChildPeer(this);
        }
        platformComponent.dispose();
        LWToolkit.targetDisposedPeer(getTarget(), this);
    }

    public final boolean isDisposed() {
        return disposed.get();
    }

    /*
     * GraphicsConfiguration is borrowed from the parent peer. The
     * return value must not be null.
     *
     * Overridden in LWWindowPeer.
     */
    @Override
    public GraphicsConfiguration getGraphicsConfiguration() {
        // Don't check windowPeer for null as it can only happen
        // for windows, but this method is overridden in
        // LWWindowPeer and doesn't call super()
        return getWindowPeer().getGraphicsConfiguration();
    }


    // Just a helper method
    public final LWGraphicsConfig getLWGC() {
        return (LWGraphicsConfig) getGraphicsConfiguration();
    }

    /*
     * Overridden in LWWindowPeer to replace its surface
     * data and back buffer.
     */
    @Override
    public boolean updateGraphicsData(GraphicsConfiguration gc) {
        // TODO: not implemented
//        throw new RuntimeException("Has not been implemented yet.");
        return false;
    }

    @Override
    public Graphics getGraphics() {
        final Graphics g = getOnscreenGraphics();
        if (g != null) {
            synchronized (getPeerTreeLock()){
                applyConstrain(g);
            }
        }
        return g;
    }

    /*
     * Peer Graphics is borrowed from the parent peer, while
     * foreground and background colors and font are specific to
     * this peer.
     */
    public final Graphics getOnscreenGraphics() {
        final LWWindowPeer wp = getWindowPeerOrSelf();
        return wp.getOnscreenGraphics(getForeground(), getBackground(),
                                      getFont());

    }

    private void applyConstrain(final Graphics g) {
        final SunGraphics2D sg2d = (SunGraphics2D) g;
        final Rectangle size = localToWindow(getSize());
        sg2d.constrain(size.x, size.y, size.width, size.height, getVisibleRegion());
    }

    Region getVisibleRegion() {
        return computeVisibleRect(this, getRegion());
    }

    static final Region computeVisibleRect(final LWComponentPeer<?, ?> c,
                                           Region region) {
        final LWContainerPeer<?, ?> p = c.getContainerPeer();
        if (p != null) {
            final Rectangle r = c.getBounds();
            region = region.getTranslatedRegion(r.x, r.y);
            region = region.getIntersection(p.getRegion());
            region = region.getIntersection(p.getContentSize());
            region = p.cutChildren(region, c);
            region = computeVisibleRect(p, region);
            region = region.getTranslatedRegion(-r.x, -r.y);
        }
        return region;
    }

    @Override
    public ColorModel getColorModel() {
        // Is it a correct implementation?
        return getGraphicsConfiguration().getColorModel();
    }

    public boolean isTranslucent() {
        // Translucent windows of the top level are supported only
        return false;
    }

    @Override
    public final void createBuffers(int numBuffers, BufferCapabilities caps)
            throws AWTException {
        getLWGC().assertOperationSupported(numBuffers, caps);
        final Image buffer = getLWGC().createBackBuffer(this);
        synchronized (getStateLock()) {
            backBuffer = buffer;
        }
    }

    @Override
    public final Image getBackBuffer() {
        synchronized (getStateLock()) {
            if (backBuffer != null) {
                return backBuffer;
            }
        }
        throw new IllegalStateException("Buffers have not been created");
    }

    @Override
    public final void flip(int x1, int y1, int x2, int y2,
                     BufferCapabilities.FlipContents flipAction) {
        getLWGC().flip(this, getBackBuffer(), x1, y1, x2, y2, flipAction);
    }

    @Override
    public final void destroyBuffers() {
        final Image oldBB;
        synchronized (getStateLock()) {
            oldBB = backBuffer;
            backBuffer = null;
        }
        getLWGC().destroyBackBuffer(oldBB);
    }

    // Helper method
    public void setBounds(Rectangle r) {
        setBounds(r.x, r.y, r.width, r.height, SET_BOUNDS);
    }

    /**
     * This method could be called on the toolkit thread.
     */
    @Override
    public void setBounds(int x, int y, int w, int h, int op) {
        setBounds(x, y, w, h, op, true, false);
    }

    protected void setBounds(int x, int y, int w, int h, int op, boolean notify,
                             final boolean updateTarget) {
        Rectangle oldBounds;
        synchronized (getStateLock()) {
            oldBounds = new Rectangle(bounds);
            if ((op & (SET_LOCATION | SET_BOUNDS)) != 0) {
                bounds.x = x;
                bounds.y = y;
            }
            if ((op & (SET_SIZE | SET_BOUNDS)) != 0) {
                bounds.width = w;
                bounds.height = h;
            }
        }
        boolean moved = (oldBounds.x != x) || (oldBounds.y != y);
        boolean resized = (oldBounds.width != w) || (oldBounds.height != h);
        if (!moved && !resized) {
            return;
        }
        final D delegate = getDelegate();
        if (delegate != null) {
            synchronized (getDelegateLock()) {
                delegateContainer.setBounds(0, 0, w, h);
                delegate.setBounds(delegateContainer.getBounds());
                // TODO: the following means that the delegateContainer NEVER gets validated. That's WRONG!
                delegate.validate();
            }
        }

        final Point locationInWindow = localToWindow(0, 0);
        platformComponent.setBounds(locationInWindow.x, locationInWindow.y, w,
                                    h);
        if (notify) {
            repaintOldNewBounds(oldBounds);
            if (resized) {
                handleResize(w, h, updateTarget);
            }
            if (moved) {
                handleMove(x, y, updateTarget);
            }
        }
    }

    public final Rectangle getBounds() {
        synchronized (getStateLock()) {
            // Return a copy to prevent subsequent modifications
            return bounds.getBounds();
        }
    }

    public final Rectangle getSize() {
        synchronized (getStateLock()) {
            // Return a copy to prevent subsequent modifications
            return new Rectangle(bounds.width, bounds.height);
        }
    }

    @Override
    public Point getLocationOnScreen() {
        Point windowLocation = getWindowPeer().getLocationOnScreen();
        Point locationInWindow = localToWindow(0, 0);
        return new Point(windowLocation.x + locationInWindow.x,
                windowLocation.y + locationInWindow.y);
    }

    /**
     * Returns the cursor of the peer, which is cursor of the target by default,
     * but peer can override this behavior.
     *
     * @param p Point relative to the peer.
     * @return Cursor of the peer or null if default cursor should be used.
     */
    Cursor getCursor(final Point p) {
        return getTarget().getCursor();
    }

    @Override
    public void setBackground(final Color c) {
        final Color oldBg = getBackground();
        if (oldBg == c || (oldBg != null && oldBg.equals(c))) {
            return;
        }
        synchronized (getStateLock()) {
            background = c;
        }
        final D delegate = getDelegate();
        if (delegate != null) {
            synchronized (getDelegateLock()) {
                // delegate will repaint the target
                delegate.setBackground(c);
            }
        } else {
            repaintPeer();
        }
    }

    public final Color getBackground() {
        synchronized (getStateLock()) {
            return background;
        }
    }

    @Override
    public void setForeground(final Color c) {
        final Color oldFg = getForeground();
        if (oldFg == c || (oldFg != null && oldFg.equals(c))) {
            return;
        }
        synchronized (getStateLock()) {
            foreground = c;
        }
        final D delegate = getDelegate();
        if (delegate != null) {
            synchronized (getDelegateLock()) {
                // delegate will repaint the target
                delegate.setForeground(c);
            }
        } else {
            repaintPeer();
        }
    }

    protected final Color getForeground() {
        synchronized (getStateLock()) {
            return foreground;
        }
    }

    @Override
    public void setFont(final Font f) {
        final Font oldF = getFont();
        if (oldF == f || (oldF != null && oldF.equals(f))) {
            return;
        }
        synchronized (getStateLock()) {
            font = f;
        }
        final D delegate = getDelegate();
        if (delegate != null) {
            synchronized (getDelegateLock()) {
                // delegate will repaint the target
                delegate.setFont(f);
            }
        } else {
            repaintPeer();
        }
    }

    protected final Font getFont() {
        synchronized (getStateLock()) {
            return font;
        }
    }

    @Override
    public FontMetrics getFontMetrics(final Font f) {
        // Borrow the metrics from the top-level window
//        return getWindowPeer().getFontMetrics(f);
        // Obtain the metrics from the offscreen window where this peer is
        // mostly drawn to.
        // TODO: check for "use platform metrics" settings
        final Graphics g = getOnscreenGraphics();
        if (g != null) {
            try {
                return g.getFontMetrics(f);
            } finally {
                g.dispose();
            }
        }
        synchronized (getDelegateLock()) {
            return delegateContainer.getFontMetrics(f);
        }
    }

    @Override
    public void setEnabled(final boolean e) {
        boolean status = e;
        final LWComponentPeer<?, ?> cp = getContainerPeer();
        if (cp != null) {
            status &= cp.isEnabled();
        }
        synchronized (getStateLock()) {
            if (enabled == status) {
                return;
            }
            enabled = status;
        }

        final D delegate = getDelegate();

        if (delegate != null) {
            synchronized (getDelegateLock()) {
                delegate.setEnabled(status);
            }
        } else {
            repaintPeer();
        }
    }

    // Helper method
    public final boolean isEnabled() {
        synchronized (getStateLock()) {
            return enabled;
        }
    }

    @Override
    public void setVisible(final boolean v) {
        synchronized (getStateLock()) {
            if (visible == v) {
                return;
            }
            visible = v;
        }
        setVisibleImpl(v);
    }

    protected void setVisibleImpl(final boolean v) {
        final D delegate = getDelegate();

        if (delegate != null) {
            synchronized (getDelegateLock()) {
                delegate.setVisible(v);
            }
        }
        if (visible) {
            repaintPeer();
        } else {
            repaintParent(getBounds());
        }
    }

    // Helper method
    public final boolean isVisible() {
        synchronized (getStateLock()) {
            return visible;
        }
    }

    @Override
    public void paint(final Graphics g) {
        getTarget().paint(g);
    }

    @Override
    public void print(final Graphics g) {
        getTarget().print(g);
    }

    @Override
    public void reparent(ContainerPeer newContainer) {
        // TODO: not implemented
        throw new UnsupportedOperationException("ComponentPeer.reparent()");
    }

    @Override
    public boolean isReparentSupported() {
        // TODO: not implemented
        return false;
    }

    @Override
    public void setZOrder(final ComponentPeer above) {
        LWContainerPeer<?, ?> cp = getContainerPeer();
        // Don't check containerPeer for null as it can only happen
        // for windows, but this method is overridden in
        // LWWindowPeer and doesn't call super()
        cp.setChildPeerZOrder(this, (LWComponentPeer<?, ?>) above);
    }

    @Override
    public void coalescePaintEvent(PaintEvent e) {
        if (!(e instanceof IgnorePaintEvent)) {
            Rectangle r = e.getUpdateRect();
            if ((r != null) && !r.isEmpty()) {
                targetPaintArea.add(r, e.getID());
            }
        }
    }

    /*
     * Should be overridden in subclasses which use complex Swing components.
     */
    @Override
    public void layout() {
        // TODO: not implemented
    }

    @Override
    public boolean isObscured() {
        // TODO: not implemented
        return false;
    }

    @Override
    public boolean canDetermineObscurity() {
        // TODO: not implemented
        return false;
    }

    /**
     * Determines the preferred size of the component. By default forwards the
     * request to the Swing helper component. Should be overridden in subclasses
     * if required.
     */
    @Override
    public Dimension getPreferredSize() {
        final Dimension size;
        synchronized (getDelegateLock()) {
            size = getDelegate().getPreferredSize();
        }
        return validateSize(size);
    }

    /**
     * Determines the minimum size of the component. By default forwards the
     * request to the Swing helper component. Should be overridden in subclasses
     * if required.
     */
    @Override
    public Dimension getMinimumSize() {
        final Dimension size;
        synchronized (getDelegateLock()) {
            size = getDelegate().getMinimumSize();
        }
        return validateSize(size);
    }

    /**
     * In some situations delegates can return empty minimum/preferred size.
     * (For example: empty JLabel, etc), but awt components never should be
     * empty. In the XPeers or WPeers we use some magic constants, but here we
     * try to use something more useful,
     */
    private Dimension validateSize(final Dimension size) {
        if (size.width == 0 || size.height == 0) {
            final FontMetrics fm = getFontMetrics(getFont());
            size.width = fm.charWidth(WIDE_CHAR);
            size.height = fm.getHeight();
        }
        return size;
    }

    @Override
    public void updateCursorImmediately() {
        getLWToolkit().getCursorManager().updateCursor();
    }

    @Override
    public boolean isFocusable() {
        // Overridden in focusable subclasses like buttons
        return false;
    }

    @Override
    public boolean requestFocus(Component lightweightChild, boolean temporary,
                                boolean focusedWindowChangeAllowed, long time,
                                FocusEvent.Cause cause)
    {
        if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
            focusLog.finest("lightweightChild=" + lightweightChild + ", temporary=" + temporary +
                            ", focusedWindowChangeAllowed=" + focusedWindowChangeAllowed +
                            ", time= " + time + ", cause=" + cause);
        }
        if (LWKeyboardFocusManagerPeer.processSynchronousLightweightTransfer(
                getTarget(), lightweightChild, temporary,
                focusedWindowChangeAllowed, time)) {
            return true;
        }

        int result = LWKeyboardFocusManagerPeer.shouldNativelyFocusHeavyweight(
                getTarget(), lightweightChild, temporary,
                focusedWindowChangeAllowed, time, cause);
        switch (result) {
            case LWKeyboardFocusManagerPeer.SNFH_FAILURE:
                return false;
            case LWKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED:
                Window parentWindow = SunToolkit.getContainingWindow(getTarget());
                if (parentWindow == null) {
                    focusLog.fine("request rejected, parentWindow is null");
                    LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
                    return false;
                }
                final LWWindowPeer parentPeer =
                        AWTAccessor.getComponentAccessor()
                                   .getPeer(parentWindow);
                if (parentPeer == null) {
                    focusLog.fine("request rejected, parentPeer is null");
                    LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
                    return false;
                }

                // A fix for 7145768. Ensure the parent window is currently natively focused.
                // The more evident place to perform this check is in KFM.shouldNativelyFocusHeavyweight,
                // however that is the shared code and this particular problem's reproducibility has
                // platform specifics. So, it was decided to narrow down the fix to lwawt (OSX) in
                // current release. TODO: consider fixing it in the shared code.
                if (!focusedWindowChangeAllowed) {
                    LWWindowPeer decoratedPeer = parentPeer.isSimpleWindow() ?
                        LWWindowPeer.getOwnerFrameDialog(parentPeer) : parentPeer;

                    if (decoratedPeer == null || !decoratedPeer.getPlatformWindow().isActive()) {
                        if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
                            focusLog.fine("request rejected, focusedWindowChangeAllowed==false, " +
                                          "decoratedPeer is inactive: " + decoratedPeer);
                        }
                        LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
                        return false;
                    }
                }

                boolean res = parentPeer.requestWindowFocus(cause);
                // If parent window can be made focused and has been made focused (synchronously)
                // then we can proceed with children, otherwise we retreat
                if (!res || !parentWindow.isFocused()) {
                    if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
                        focusLog.fine("request rejected, res= " + res + ", parentWindow.isFocused()=" +
                                      parentWindow.isFocused());
                    }
                    LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
                    return false;
                }

                KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
                Component focusOwner = kfmPeer.getCurrentFocusOwner();
                return LWKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
                        getTarget(), temporary,
                        focusedWindowChangeAllowed,
                        time, cause, focusOwner);

            case LWKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
                return true;
        }

        return false;
    }

    @Override
    public final Image createImage(final ImageProducer producer) {
        return new ToolkitImage(producer);
    }

    @Override
    public final Image createImage(final int width, final int height) {
        return getLWGC().createAcceleratedImage(getTarget(), width, height);
    }

    @Override
    public final VolatileImage createVolatileImage(final int w, final int h) {
        return new SunVolatileImage(getTarget(), w, h);
    }

    @Override
    public boolean prepareImage(Image img, int w, int h, ImageObserver o) {
        // TODO: is it a right/complete implementation?
        return Toolkit.getDefaultToolkit().prepareImage(img, w, h, o);
    }

    @Override
    public int checkImage(Image img, int w, int h, ImageObserver o) {
        // TODO: is it a right/complete implementation?
        return Toolkit.getDefaultToolkit().checkImage(img, w, h, o);
    }

    @Override
    public boolean handlesWheelScrolling() {
        // TODO: not implemented
        return false;
    }

    @Override
    public final void applyShape(final Region shape) {
        synchronized (getStateLock()) {
            if (region == shape || (region != null && region.equals(shape))) {
                return;
            }
        }
        applyShapeImpl(shape);
    }

    void applyShapeImpl(final Region shape) {
        synchronized (getStateLock()) {
            if (shape != null) {
                region = Region.WHOLE_REGION.getIntersection(shape);
            } else {
                region = null;
            }
        }
        repaintParent(getBounds());
    }

    protected final Region getRegion() {
        synchronized (getStateLock()) {
            return isShaped() ? region : Region.getInstance(getSize());
        }
    }

    public boolean isShaped() {
        synchronized (getStateLock()) {
            return region != null;
        }
    }

    // DropTargetPeer Method
    @Override
    public void addDropTarget(DropTarget dt) {
        LWWindowPeer winPeer = getWindowPeerOrSelf();
        if (winPeer != null && winPeer != this) {
            // We need to register the DropTarget in the
            // peer of the window ancestor of the component
            winPeer.addDropTarget(dt);
        } else {
            synchronized (dropTargetLock) {
                // 10-14-02 VL: Windows WComponentPeer would add (or remove) the drop target only
                // if it's the first (or last) one for the component. Otherwise this call is a no-op.
                if (++fNumDropTargets == 1) {
                    // Having a non-null drop target would be an error but let's check just in case:
                    if (fDropTarget != null) {
                        throw new IllegalStateException("Current drop target is not null");
                    }
                    // Create a new drop target:
                    fDropTarget = LWToolkit.getLWToolkit().createDropTarget(dt, target, this);
                }
            }
        }
    }

    // DropTargetPeer Method
    @Override
    public void removeDropTarget(DropTarget dt) {
        LWWindowPeer winPeer = getWindowPeerOrSelf();
        if (winPeer != null && winPeer != this) {
            // We need to unregister the DropTarget in the
            // peer of the window ancestor of the component
            winPeer.removeDropTarget(dt);
        } else {
            synchronized (dropTargetLock){
                // 10-14-02 VL: Windows WComponentPeer would add (or remove) the drop target only
                // if it's the first (or last) one for the component. Otherwise this call is a no-op.
                if (--fNumDropTargets == 0) {
                    // Having a null drop target would be an error but let's check just in case:
                    if (fDropTarget != null) {
                        // Dispose of the drop target:
                        fDropTarget.dispose();
                        fDropTarget = null;
                    } else
                        System.err.println("CComponent.removeDropTarget(): current drop target is null.");
                }
            }
        }
    }

    // ---- PEER NOTIFICATIONS ---- //

    /**
     * Called when this peer's location has been changed either as a result
     * of target.setLocation() or as a result of user actions (window is
     * dragged with mouse).
     *
     * This method could be called on the toolkit thread.
     */
    protected final void handleMove(final int x, final int y,
                                    final boolean updateTarget) {
        if (updateTarget) {
            AWTAccessor.getComponentAccessor().setLocation(getTarget(), x, y);
        }
        postEvent(new ComponentEvent(getTarget(),
                                     ComponentEvent.COMPONENT_MOVED));
    }

    /**
     * Called when this peer's size has been changed either as a result of
     * target.setSize() or as a result of user actions (window is resized).
     *
     * This method could be called on the toolkit thread.
     */
    protected final void handleResize(final int w, final int h,
                                      final boolean updateTarget) {
        Image oldBB = null;
        synchronized (getStateLock()) {
            if (backBuffer != null) {
                oldBB = backBuffer;
                backBuffer = getLWGC().createBackBuffer(this);
            }
        }
        getLWGC().destroyBackBuffer(oldBB);

        if (updateTarget) {
            AWTAccessor.getComponentAccessor().setSize(getTarget(), w, h);
        }
        postEvent(new ComponentEvent(getTarget(),
                                     ComponentEvent.COMPONENT_RESIZED));
    }

    protected final void repaintOldNewBounds(final Rectangle oldB) {
        repaintParent(oldB);
        repaintPeer(getSize());
    }

    protected final void repaintParent(final Rectangle oldB) {
        final LWContainerPeer<?, ?> cp = getContainerPeer();
        if (cp != null) {
            // Repaint unobscured part of the parent
            cp.repaintPeer(cp.getContentSize().intersection(oldB));
        }
    }

    // ---- EVENTS ---- //

    /**
     * Post an event to the proper Java EDT.
     */
    public void postEvent(final AWTEvent event) {
        LWToolkit.postEvent(event);
    }

    protected void postPaintEvent(int x, int y, int w, int h) {
        // TODO: call getIgnoreRepaint() directly with the right ACC
        if (AWTAccessor.getComponentAccessor().getIgnoreRepaint(target)) {
            return;
        }
        PaintEvent event = PaintEventDispatcher.getPaintEventDispatcher().
                createPaintEvent(getTarget(), x, y, w, h);
        if (event != null) {
            postEvent(event);
        }
    }

    /*
     * Gives a chance for the peer to handle the event after it's been
     * processed by the target.
     */
    @Override
    public void handleEvent(AWTEvent e) {
        if ((e instanceof InputEvent) && ((InputEvent) e).isConsumed()) {
            return;
        }
        switch (e.getID()) {
            case FocusEvent.FOCUS_GAINED:
            case FocusEvent.FOCUS_LOST:
                handleJavaFocusEvent((FocusEvent) e);
                break;
            case PaintEvent.PAINT:
                // Got a native paint event
//                paintPending = false;
                // fall through to the next statement
            case PaintEvent.UPDATE:
                handleJavaPaintEvent();
                break;
            case MouseEvent.MOUSE_PRESSED:
                handleJavaMouseEvent((MouseEvent)e);
        }

        sendEventToDelegate(e);
    }

    protected void sendEventToDelegate(final AWTEvent e) {
        if (getDelegate() == null || !isShowing() || !isEnabled()) {
            return;
        }
        synchronized (getDelegateLock()) {
            AWTEvent delegateEvent = createDelegateEvent(e);
            if (delegateEvent != null) {
                AWTAccessor.getComponentAccessor()
                        .processEvent((Component) delegateEvent.getSource(),
                                delegateEvent);
                if (delegateEvent instanceof KeyEvent) {
                    KeyEvent ke = (KeyEvent) delegateEvent;
                    SwingUtilities.processKeyBindings(ke);
                }
            }
        }
    }

    /**
     * Changes the target of the AWTEvent from awt component to appropriate
     * swing delegate.
     */
    @SuppressWarnings("deprecation")
    private AWTEvent createDelegateEvent(final AWTEvent e) {
        // TODO modifiers should be changed to getModifiers()|getModifiersEx()?
        AWTEvent delegateEvent = null;
        if (e instanceof MouseWheelEvent) {
            MouseWheelEvent me = (MouseWheelEvent) e;
            delegateEvent = new MouseWheelEvent(
                    delegate, me.getID(), me.getWhen(),
                    me.getModifiers(),
                    me.getX(), me.getY(),
                    me.getXOnScreen(), me.getYOnScreen(),
                    me.getClickCount(),
                    me.isPopupTrigger(),
                    me.getScrollType(),
                    me.getScrollAmount(),
                    me.getWheelRotation(),
                    me.getPreciseWheelRotation());
        } else if (e instanceof MouseEvent) {
            MouseEvent me = (MouseEvent) e;

            Component eventTarget = SwingUtilities.getDeepestComponentAt(delegate, me.getX(), me.getY());

            if (me.getID() == MouseEvent.MOUSE_DRAGGED) {
                if (delegateDropTarget == null) {
                    delegateDropTarget = eventTarget;
                } else {
                    eventTarget = delegateDropTarget;
                }
            }
            if (me.getID() == MouseEvent.MOUSE_RELEASED && delegateDropTarget != null) {
                eventTarget = delegateDropTarget;
                delegateDropTarget = null;
            }
            if (eventTarget == null) {
                eventTarget = delegate;
            }
            delegateEvent = SwingUtilities.convertMouseEvent(getTarget(), me, eventTarget);
        } else if (e instanceof KeyEvent) {
            KeyEvent ke = (KeyEvent) e;
            delegateEvent = new KeyEvent(getDelegateFocusOwner(), ke.getID(), ke.getWhen(),
                    ke.getModifiers(), ke.getKeyCode(), ke.getKeyChar(), ke.getKeyLocation());
            AWTAccessor.getKeyEventAccessor().setExtendedKeyCode((KeyEvent) delegateEvent,
                    ke.getExtendedKeyCode());
        } else if (e instanceof FocusEvent) {
            FocusEvent fe = (FocusEvent) e;
            delegateEvent = new FocusEvent(getDelegateFocusOwner(), fe.getID(), fe.isTemporary());
        }
        return delegateEvent;
    }

    protected void handleJavaMouseEvent(MouseEvent e) {
        Component target = getTarget();
        assert (e.getSource() == target);

        if (!target.isFocusOwner() && LWKeyboardFocusManagerPeer.shouldFocusOnClick(target)) {
            LWKeyboardFocusManagerPeer.requestFocusFor(target, FocusEvent.Cause.MOUSE_EVENT);
        }
    }

    /**
     * Handler for FocusEvents.
     */
    void handleJavaFocusEvent(final FocusEvent e) {
        // Note that the peer receives all the FocusEvents from
        // its lightweight children as well
        KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
        kfmPeer.setCurrentFocusOwner(e.getID() == FocusEvent.FOCUS_GAINED ? getTarget() : null);
    }

    /**
     * All peers should clear background before paint.
     *
     * @return false on components that DO NOT require a clearRect() before
     *         painting.
     */
    protected final boolean shouldClearRectBeforePaint() {
        // TODO: sun.awt.noerasebackground
        return true;
    }

    /**
     * Handler for PAINT and UPDATE PaintEvents.
     */
    private void handleJavaPaintEvent() {
        // Skip all painting while layouting and all UPDATEs
        // while waiting for native paint
//        if (!isLayouting && !paintPending) {
        if (!isLayouting()) {
            targetPaintArea.paint(getTarget(), shouldClearRectBeforePaint());
        }
    }

    // ---- UTILITY METHODS ---- //

    /**
     * Finds a top-most visible component for the given point. The location is
     * specified relative to the peer's parent.
     */
    LWComponentPeer<?, ?> findPeerAt(final int x, final int y) {
        final Rectangle r = getBounds();
        final Region sh = getRegion();
        final boolean found = isVisible() && sh.contains(x - r.x, y - r.y);
        return found ? this : null;
    }

    /*
     * Translated the given point in Window coordinates to the point in
     * coordinates local to this component. The given window peer must be
     * the window where this component is in.
     */
    public Point windowToLocal(int x, int y, LWWindowPeer wp) {
        return windowToLocal(new Point(x, y), wp);
    }

    public Point windowToLocal(Point p, LWWindowPeer wp) {
        LWComponentPeer<?, ?> cp = this;
        while (cp != wp) {
            Rectangle cpb = cp.getBounds();
            p.x -= cpb.x;
            p.y -= cpb.y;
            cp = cp.getContainerPeer();
        }
        // Return a copy to prevent subsequent modifications
        return new Point(p);
    }

    public Rectangle windowToLocal(Rectangle r, LWWindowPeer wp) {
        Point p = windowToLocal(r.getLocation(), wp);
        return new Rectangle(p, r.getSize());
    }

    public Point localToWindow(int x, int y) {
        return localToWindow(new Point(x, y));
    }

    public Point localToWindow(Point p) {
        LWComponentPeer<?, ?> cp = getContainerPeer();
        Rectangle r = getBounds();
        while (cp != null) {
            p.x += r.x;
            p.y += r.y;
            r = cp.getBounds();
            cp = cp.getContainerPeer();
        }
        // Return a copy to prevent subsequent modifications
        return new Point(p);
    }

    public Rectangle localToWindow(Rectangle r) {
        Point p = localToWindow(r.getLocation());
        return new Rectangle(p, r.getSize());
    }

    public final void repaintPeer() {
        repaintPeer(getSize());
    }

    void repaintPeer(final Rectangle r) {
        final Rectangle toPaint = getSize().intersection(r);
        if (!isShowing() || toPaint.isEmpty()) {
            return;
        }

        postPaintEvent(toPaint.x, toPaint.y, toPaint.width, toPaint.height);
    }

    /**
     * Determines whether this peer is showing on screen. This means that the
     * peer must be visible, and it must be in a container that is visible and
     * showing.
     *
     * @see #isVisible()
     */
    protected final boolean isShowing() {
        synchronized (getPeerTreeLock()) {
            if (isVisible()) {
                final LWContainerPeer<?, ?> container = getContainerPeer();
                return (container == null) || container.isShowing();
            }
        }
        return false;
    }

    /**
     * Paints the peer. Delegate the actual painting to Swing components.
     */
    protected final void paintPeer(final Graphics g) {
        final D delegate = getDelegate();
        if (delegate != null) {
            if (!SwingUtilities.isEventDispatchThread()) {
                throw new InternalError("Painting must be done on EDT");
            }
            synchronized (getDelegateLock()) {
                // JComponent.print() is guaranteed to not affect the double buffer
                getDelegate().print(g);
            }
        }
    }

    protected static final void flushOnscreenGraphics(){
        final OGLRenderQueue rq = OGLRenderQueue.getInstance();
        rq.lock();
        try {
            rq.flushNow();
        } finally {
            rq.unlock();
        }
    }

    /**
     * Used by ContainerPeer to skip all the paint events during layout.
     *
     * @param isLayouting layouting state.
     */
    protected final void setLayouting(final boolean isLayouting) {
        this.isLayouting = isLayouting;
    }

    /**
     * Returns layouting state. Used by ComponentPeer to skip all the paint
     * events during layout.
     *
     * @return true during layout, false otherwise.
     */
    private final boolean isLayouting() {
        return isLayouting;
    }
}
