/*
 * Copyright 2002-2007 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
package sun.awt.X11;

import java.util.Vector;
import java.awt.*;
import java.awt.peer.*;
import java.awt.event.*;
import sun.awt.im.*;
import sun.awt.*;
import java.util.logging.*;
import java.lang.reflect.Field;
import java.util.*;

class XFramePeer extends XDecoratedPeer implements FramePeer, XConstants {
    private static Logger log = Logger.getLogger("sun.awt.X11.XFramePeer");
    private static Logger stateLog = Logger.getLogger("sun.awt.X11.states");
    private static Logger insLog = Logger.getLogger("sun.awt.X11.insets.XFramePeer");

    XMenuBarPeer menubarPeer;
    MenuBar menubar;
    int state;
    private Boolean undecorated;

    private static final int MENUBAR_HEIGHT_IF_NO_MENUBAR = 0;
    private int lastAppliedMenubarHeight = MENUBAR_HEIGHT_IF_NO_MENUBAR;

    XFramePeer(Frame target) {
        super(target);
    }

    XFramePeer(XCreateWindowParams params) {
        super(params);
    }

    void preInit(XCreateWindowParams params) {
        super.preInit(params);
        Frame target = (Frame)(this.target);
        // set the window attributes for this Frame
        winAttr.initialState = target.getExtendedState();
        state = 0;
        undecorated = Boolean.valueOf(target.isUndecorated());
        winAttr.nativeDecor = !target.isUndecorated();
        if (winAttr.nativeDecor) {
            winAttr.decorations = winAttr.AWT_DECOR_ALL;
        } else {
            winAttr.decorations = winAttr.AWT_DECOR_NONE;
        }
        winAttr.functions = MWM_FUNC_ALL;
        winAttr.isResizable = true; // target.isResizable();
        winAttr.title = target.getTitle();
        winAttr.initialResizability = target.isResizable();
        if (log.isLoggable(Level.FINE)) {
            log.log(Level.FINE, "Frame''s initial attributes: decor {0}, resizable {1}, undecorated {2}, initial state {3}",
                     new Object[] {Integer.valueOf(winAttr.decorations), Boolean.valueOf(winAttr.initialResizability),
                                   Boolean.valueOf(!winAttr.nativeDecor), Integer.valueOf(winAttr.initialState)});
        }
    }

    void postInit(XCreateWindowParams params) {
        super.postInit(params);
        setupState(true);
    }

    protected Insets guessInsets() {
        if (isTargetUndecorated()) {
            return new Insets(0, 0, 0, 0);
        } else {
            return super.guessInsets();
        }
    }

    private boolean isTargetUndecorated() {
        if (undecorated != null) {
            return undecorated.booleanValue();
        } else {
            return ((Frame)target).isUndecorated();
        }
    }

    void setupState(boolean onInit) {
        if (onInit) {
            state = winAttr.initialState;
        }
        if ((state & Frame.ICONIFIED) != 0) {
            setInitialState(IconicState);
        } else {
            setInitialState(NormalState);
        }
        setExtendedState(state);
    }

    public void setMenuBar(MenuBar mb) {
        // state_lock should always be the second after awt_lock
        XToolkit.awtLock();
        try {
            synchronized(getStateLock()) {
                if (mb == menubar) return;
                if (mb == null) {
                    if (menubar != null) {
                        menubarPeer.xSetVisible(false);
                        menubar = null;
                        menubarPeer.dispose();
                        menubarPeer = null;
                    }
                } else {
                    menubar = mb;
                    menubarPeer = (XMenuBarPeer) mb.getPeer();
                    if (menubarPeer != null) {
                        menubarPeer.init((Frame)target);
                    }
                }
            }
        } finally {
            XToolkit.awtUnlock();
        }

        reshapeMenubarPeer();
    }

    XMenuBarPeer getMenubarPeer() {
        return menubarPeer;
    }

    int getMenuBarHeight() {
        if (menubarPeer != null) {
            return menubarPeer.getDesiredHeight();
        } else {
            return MENUBAR_HEIGHT_IF_NO_MENUBAR;
        }
    }

    void updateChildrenSizes() {
        super.updateChildrenSizes();
        // XWindow.reshape calls XBaseWindow.xSetBounds, which acquires
        // the AWT lock, so we have to acquire the AWT lock here
        // before getStateLock() to avoid a deadlock with the Toolkit thread
        // when this method is called on the EDT.
        XToolkit.awtLock();
        try {
            synchronized(getStateLock()) {
                int width = dimensions.getClientSize().width;
                if (menubarPeer != null) {
                    menubarPeer.reshape(0, 0, width, getMenuBarHeight());
                }
            }
        } finally {
            XToolkit.awtUnlock();
        }
    }

    /**
     * In addition to reshaping menubarPeer (by using 'updateChildrenSizes')
     * this method also performs some frame reaction on this (i.e. layouts
     * other frame children, if required)
     */
    final void reshapeMenubarPeer() {
        XToolkit.executeOnEventHandlerThread(
            target,
            new Runnable() {
                public void run() {
                    updateChildrenSizes();
                    boolean heightChanged = false;

                    int height = getMenuBarHeight();
                        // Neither 'XToolkit.awtLock()' nor 'getStateLock()'
                        // is acquired under this call, and it looks to run
                        // thread-safely. I currently see no reason to move
                        // it under following 'synchronized' clause.

                    synchronized(getStateLock()) {
                        if (height != lastAppliedMenubarHeight) {
                            lastAppliedMenubarHeight = height;
                            heightChanged = true;
                        }
                    }
                    if (heightChanged) {
                        // To make frame contents be re-layout (copied from
                        // 'XDecoratedPeer.revalidate()'). These are not
                        // 'synchronized', because can recursively call client
                        // methods, which are not supposed to be called with locks
                        // acquired.
                        target.invalidate();
                        target.validate();
                    }
                }
            }
        );
    }

    public void setMaximizedBounds(Rectangle b) {
        if (insLog.isLoggable(Level.FINE)) insLog.fine("Setting maximized bounds to " + b);
        if (b == null) return;
        maxBounds = new Rectangle(b);
        XToolkit.awtLock();
        try {
            XSizeHints hints = getHints();
            hints.set_flags(hints.get_flags() | (int)XlibWrapper.PMaxSize);
            if (b.width != Integer.MAX_VALUE) {
                hints.set_max_width(b.width);
            } else {
                hints.set_max_width((int)XlibWrapper.DisplayWidth(XToolkit.getDisplay(), XlibWrapper.DefaultScreen(XToolkit.getDisplay())));
            }
            if (b.height != Integer.MAX_VALUE) {
                hints.set_max_height(b.height);
            } else {
                hints.set_max_height((int)XlibWrapper.DisplayHeight(XToolkit.getDisplay(), XlibWrapper.DefaultScreen(XToolkit.getDisplay())));
            }
            if (insLog.isLoggable(Level.FINER)) insLog.finer("Setting hints, flags " + XlibWrapper.hintsToString(hints.get_flags()));
            XlibWrapper.XSetWMNormalHints(XToolkit.getDisplay(), window, hints.pData);
        } finally {
            XToolkit.awtUnlock();
        }
    }

    public int getState() { return state; }

    public void setState(int newState) {
        if (!isShowing()) {
            stateLog.finer("Frame is not showing");
            state = newState;
            return;
        }
        changeState(newState);
    }

    void changeState(int newState) {
        int changed = state ^ newState;
        int changeIconic = changed & Frame.ICONIFIED;
        boolean iconic = (newState & Frame.ICONIFIED) != 0;
        stateLog.log(Level.FINER, "Changing state, old state {0}, new state {1}(iconic {2})",
                     new Object[] {Integer.valueOf(state), Integer.valueOf(newState), Boolean.valueOf(iconic)});
        if (changeIconic != 0 && iconic) {
            if (stateLog.isLoggable(Level.FINER)) stateLog.finer("Iconifying shell " + getShell() + ", this " + this + ", screen " + getScreenNumber());
            XToolkit.awtLock();
            try {
                int res = XlibWrapper.XIconifyWindow(XToolkit.getDisplay(), getShell(), getScreenNumber());
                if (stateLog.isLoggable(Level.FINER)) stateLog.finer("XIconifyWindow returned " + res);
            }
            finally {
                XToolkit.awtUnlock();
            }
        }
        if ((changed & ~Frame.ICONIFIED) != 0) {
            setExtendedState(newState);
        }
        if (changeIconic != 0 && !iconic) {
            if (stateLog.isLoggable(Level.FINER)) stateLog.finer("DeIconifying " + this);
            xSetVisible(true);
        }
    }

    void setExtendedState(int newState) {
        XWM.getWM().setExtendedState(this, newState);
    }

    public void handlePropertyNotify(XEvent xev) {
        super.handlePropertyNotify(xev);
        XPropertyEvent ev = xev.get_xproperty();

        log.log(Level.FINER, "Property change {0}", new Object[] {ev});
        /*
         * Let's see if this is a window state protocol message, and
         * if it is - decode a new state in terms of java constants.
         */
        Integer newState = XWM.getWM().isStateChange(this, ev);
        if (newState == null) {
            return;
        }

        int changed = state ^ newState.intValue();
        if (changed == 0) {
            stateLog.finer("State is the same: " + state);
            return;
        }

        int old_state = state;
        state = newState.intValue();

        if ((changed & Frame.ICONIFIED) != 0) {
            if ((state & Frame.ICONIFIED) != 0) {
                stateLog.finer("Iconified");
                handleIconify();
            } else {
                stateLog.finer("DeIconified");
                content.purgeIconifiedExposeEvents();
                handleDeiconify();
            }
        }
        handleStateChange(old_state, state);
    }

    // NOTE: This method may be called by privileged threads.
    //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
    public void handleStateChange(int oldState, int newState) {
        super.handleStateChange(oldState, newState);
        for (ToplevelStateListener topLevelListenerTmp : toplevelStateListeners) {
            topLevelListenerTmp.stateChangedJava(oldState, newState);
        }
    }

    public void setVisible(boolean vis) {
        if (vis) {
            setupState(false);
        } else {
            if ((state & Frame.MAXIMIZED_BOTH) != 0) {
                XWM.getWM().setExtendedState(this, state & ~Frame.MAXIMIZED_BOTH);
            }
        }
        super.setVisible(vis);
        if (vis && maxBounds != null) {
            setMaximizedBounds(maxBounds);
        }
    }

    void setInitialState(int wm_state) {
        XToolkit.awtLock();
        try {
            XWMHints hints = getWMHints();
            hints.set_flags((int)XlibWrapper.StateHint | hints.get_flags());
            hints.set_initial_state(wm_state);
            if (stateLog.isLoggable(Level.FINE)) stateLog.fine("Setting initial WM state on " + this + " to " + wm_state);
            XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData);
        }
        finally {
            XToolkit.awtUnlock();
        }
    }

    public void dispose() {
        if (menubarPeer != null) {
            menubarPeer.dispose();
        }
        super.dispose();
    }

    boolean isMaximized() {
        return (state & (Frame.MAXIMIZED_VERT  | Frame.MAXIMIZED_HORIZ)) != 0;
    }




    static final int CROSSHAIR_INSET = 5;

    static final int BUTTON_Y = CROSSHAIR_INSET + 1;
    static final int BUTTON_W = 17;
    static final int BUTTON_H = 17;

    static final int SYS_MENU_X = CROSSHAIR_INSET + 1;
    static final int SYS_MENU_CONTAINED_X = SYS_MENU_X + 5;
    static final int SYS_MENU_CONTAINED_Y = BUTTON_Y + 7;
    static final int SYS_MENU_CONTAINED_W = 8;
    static final int SYS_MENU_CONTAINED_H = 3;

    static final int MAXIMIZE_X_DIFF = CROSSHAIR_INSET + BUTTON_W;
    static final int MAXIMIZE_CONTAINED_X_DIFF = MAXIMIZE_X_DIFF - 5;
    static final int MAXIMIZE_CONTAINED_Y = BUTTON_Y + 5;
    static final int MAXIMIZE_CONTAINED_W = 8;
    static final int MAXIMIZE_CONTAINED_H = 8;

    static final int MINIMIZE_X_DIFF = MAXIMIZE_X_DIFF + BUTTON_W;
    static final int MINIMIZE_CONTAINED_X_DIFF = MINIMIZE_X_DIFF - 7;
    static final int MINIMIZE_CONTAINED_Y = BUTTON_Y + 7;
    static final int MINIMIZE_CONTAINED_W = 3;
    static final int MINIMIZE_CONTAINED_H = 3;

    static final int TITLE_X = SYS_MENU_X + BUTTON_W;
    static final int TITLE_W_DIFF = BUTTON_W * 3 + CROSSHAIR_INSET * 2 - 1;
    static final int TITLE_MID_Y = BUTTON_Y + (BUTTON_H / 2);

    static final int MENUBAR_X = CROSSHAIR_INSET + 1;
    static final int MENUBAR_Y = BUTTON_Y + BUTTON_H;

    static final int HORIZ_RESIZE_INSET = CROSSHAIR_INSET + BUTTON_H;
    static final int VERT_RESIZE_INSET = CROSSHAIR_INSET + BUTTON_W;


    /*
     * Print the native component by rendering the Motif look ourselves.
     * We also explicitly print the MenuBar since a MenuBar isn't a subclass
     * of Component (and thus it has no "print" method which gets called by
     * default).
     */
    public void print(Graphics g) {
        super.print(g);

        Frame f = (Frame)target;
        Insets finsets = f.getInsets();
        Dimension fsize = f.getSize();

        Color bg = f.getBackground();
        Color fg = f.getForeground();
        Color highlight = bg.brighter();
        Color shadow = bg.darker();

        // Well, we could query for the currently running window manager
        // and base the look on that, or we could just always do dtwm.
        // aim, tball, and levenson all agree we'll just do dtwm.

        if (hasDecorations(XWindowAttributesData.AWT_DECOR_BORDER)) {

            // top outer -- because we'll most likely be drawing on white paper,
            // for aesthetic reasons, don't make any part of the outer border
            // pure white
            if (highlight.equals(Color.white)) {
                g.setColor(new Color(230, 230, 230));
            }
            else {
                g.setColor(highlight);
            }
            g.drawLine(0, 0, fsize.width, 0);
            g.drawLine(0, 1, fsize.width - 1, 1);

            // left outer
            // if (highlight.equals(Color.white)) {
            //     g.setColor(new Color(230, 230, 230));
            // }
            // else {
            //     g.setColor(highlight);
            // }
            g.drawLine(0, 0, 0, fsize.height);
            g.drawLine(1, 0, 1, fsize.height - 1);

            // bottom cross-hair
            g.setColor(highlight);
            g.drawLine(CROSSHAIR_INSET + 1, fsize.height - CROSSHAIR_INSET,
                       fsize.width - CROSSHAIR_INSET,
                       fsize.height - CROSSHAIR_INSET);

            // right cross-hair
            // g.setColor(highlight);
            g.drawLine(fsize.width - CROSSHAIR_INSET, CROSSHAIR_INSET + 1,
                       fsize.width - CROSSHAIR_INSET,
                       fsize.height - CROSSHAIR_INSET);

            // bottom outer
            g.setColor(shadow);
            g.drawLine(1, fsize.height, fsize.width, fsize.height);
            g.drawLine(2, fsize.height - 1, fsize.width, fsize.height - 1);

            // right outer
            // g.setColor(shadow);
            g.drawLine(fsize.width, 1, fsize.width, fsize.height);
            g.drawLine(fsize.width - 1, 2, fsize.width - 1, fsize.height);

            // top cross-hair
            // g.setColor(shadow);
            g.drawLine(CROSSHAIR_INSET, CROSSHAIR_INSET,
                       fsize.width - CROSSHAIR_INSET, CROSSHAIR_INSET);

            // left cross-hair
            // g.setColor(shadow);
            g.drawLine(CROSSHAIR_INSET, CROSSHAIR_INSET, CROSSHAIR_INSET,
                       fsize.height - CROSSHAIR_INSET);
        }

        if (hasDecorations(XWindowAttributesData.AWT_DECOR_TITLE)) {

            if (hasDecorations(XWindowAttributesData.AWT_DECOR_MENU)) {

                // system menu
                g.setColor(bg);
                g.fill3DRect(SYS_MENU_X, BUTTON_Y, BUTTON_W, BUTTON_H, true);
                g.fill3DRect(SYS_MENU_CONTAINED_X, SYS_MENU_CONTAINED_Y,
                             SYS_MENU_CONTAINED_W, SYS_MENU_CONTAINED_H, true);
            }

            // title bar
            // g.setColor(bg);
            g.fill3DRect(TITLE_X, BUTTON_Y, fsize.width - TITLE_W_DIFF, BUTTON_H,
                         true);

            if (hasDecorations(XWindowAttributesData.AWT_DECOR_MINIMIZE)) {

                // minimize button
                // g.setColor(bg);
                g.fill3DRect(fsize.width - MINIMIZE_X_DIFF, BUTTON_Y, BUTTON_W,
                             BUTTON_H, true);
                g.fill3DRect(fsize.width - MINIMIZE_CONTAINED_X_DIFF,
                             MINIMIZE_CONTAINED_Y, MINIMIZE_CONTAINED_W,
                             MINIMIZE_CONTAINED_H, true);
            }

            if (hasDecorations(XWindowAttributesData.AWT_DECOR_MAXIMIZE)) {

                // maximize button
                // g.setColor(bg);
                g.fill3DRect(fsize.width - MAXIMIZE_X_DIFF, BUTTON_Y, BUTTON_W,
                             BUTTON_H, true);
                g.fill3DRect(fsize.width - MAXIMIZE_CONTAINED_X_DIFF,
                             MAXIMIZE_CONTAINED_Y, MAXIMIZE_CONTAINED_W,
                             MAXIMIZE_CONTAINED_H, true);
            }

            // title bar text
            g.setColor(fg);
            Font sysfont = new Font(Font.SANS_SERIF, Font.PLAIN, 10);
            g.setFont(sysfont);
            FontMetrics sysfm = g.getFontMetrics();
            String ftitle = f.getTitle();
            g.drawString(ftitle,
                         ((TITLE_X + TITLE_X + fsize.width - TITLE_W_DIFF) / 2) -
                         (sysfm.stringWidth(ftitle) / 2),
                         TITLE_MID_Y + sysfm.getMaxDescent());
        }

        if (f.isResizable() &&
            hasDecorations(XWindowAttributesData.AWT_DECOR_RESIZEH)) {

            // add resize cross hairs

            // upper-left horiz (shadow)
            g.setColor(shadow);
            g.drawLine(1, HORIZ_RESIZE_INSET, CROSSHAIR_INSET,
                       HORIZ_RESIZE_INSET);
            // upper-left vert (shadow)
            // g.setColor(shadow);
            g.drawLine(VERT_RESIZE_INSET, 1, VERT_RESIZE_INSET, CROSSHAIR_INSET);
            // upper-right horiz (shadow)
            // g.setColor(shadow);
            g.drawLine(fsize.width - CROSSHAIR_INSET + 1, HORIZ_RESIZE_INSET,
                       fsize.width, HORIZ_RESIZE_INSET);
            // upper-right vert (shadow)
            // g.setColor(shadow);
            g.drawLine(fsize.width - VERT_RESIZE_INSET - 1, 2,
                       fsize.width - VERT_RESIZE_INSET - 1, CROSSHAIR_INSET + 1);
            // lower-left horiz (shadow)
            // g.setColor(shadow);
            g.drawLine(1, fsize.height - HORIZ_RESIZE_INSET - 1,
                       CROSSHAIR_INSET, fsize.height - HORIZ_RESIZE_INSET - 1);
            // lower-left vert (shadow)
            // g.setColor(shadow);
            g.drawLine(VERT_RESIZE_INSET, fsize.height - CROSSHAIR_INSET + 1,
                       VERT_RESIZE_INSET, fsize.height);
            // lower-right horiz (shadow)
            // g.setColor(shadow);
            g.drawLine(fsize.width - CROSSHAIR_INSET + 1,
                       fsize.height - HORIZ_RESIZE_INSET - 1, fsize.width,
                       fsize.height - HORIZ_RESIZE_INSET - 1);
            // lower-right vert (shadow)
            // g.setColor(shadow);
            g.drawLine(fsize.width - VERT_RESIZE_INSET - 1,
                       fsize.height - CROSSHAIR_INSET + 1,
                       fsize.width - VERT_RESIZE_INSET - 1, fsize.height);

            // upper-left horiz (highlight)
            g.setColor(highlight);
            g.drawLine(2, HORIZ_RESIZE_INSET + 1, CROSSHAIR_INSET,
                       HORIZ_RESIZE_INSET + 1);
            // upper-left vert (highlight)
            // g.setColor(highlight);
            g.drawLine(VERT_RESIZE_INSET + 1, 2, VERT_RESIZE_INSET + 1,
                       CROSSHAIR_INSET);
            // upper-right horiz (highlight)
            // g.setColor(highlight);
            g.drawLine(fsize.width - CROSSHAIR_INSET + 1,
                       HORIZ_RESIZE_INSET + 1, fsize.width - 1,
                       HORIZ_RESIZE_INSET + 1);
            // upper-right vert (highlight)
            // g.setColor(highlight);
            g.drawLine(fsize.width - VERT_RESIZE_INSET, 2,
                       fsize.width - VERT_RESIZE_INSET, CROSSHAIR_INSET);
            // lower-left horiz (highlight)
            // g.setColor(highlight);
            g.drawLine(2, fsize.height - HORIZ_RESIZE_INSET, CROSSHAIR_INSET,
                       fsize.height - HORIZ_RESIZE_INSET);
            // lower-left vert (highlight)
            // g.setColor(highlight);
            g.drawLine(VERT_RESIZE_INSET + 1,
                       fsize.height - CROSSHAIR_INSET + 1,
                       VERT_RESIZE_INSET + 1, fsize.height - 1);
            // lower-right horiz (highlight)
            // g.setColor(highlight);
            g.drawLine(fsize.width - CROSSHAIR_INSET + 1,
                       fsize.height - HORIZ_RESIZE_INSET, fsize.width - 1,
                       fsize.height - HORIZ_RESIZE_INSET);
            // lower-right vert (highlight)
            // g.setColor(highlight);
            g.drawLine(fsize.width - VERT_RESIZE_INSET,
                       fsize.height - CROSSHAIR_INSET + 1,
                       fsize.width - VERT_RESIZE_INSET, fsize.height - 1);
        }

        XMenuBarPeer peer = menubarPeer;
        if (peer != null) {
            Insets insets = getInsets();
            Graphics ng = g.create();
            int menubarX = 0;
            int menubarY = 0;
            if (hasDecorations(XWindowAttributesData.AWT_DECOR_BORDER)) {
                menubarX += CROSSHAIR_INSET + 1;
                    menubarY += CROSSHAIR_INSET + 1;
            }
            if (hasDecorations(XWindowAttributesData.AWT_DECOR_TITLE)) {
                menubarY += BUTTON_H;
            }
            try {
                ng.translate(menubarX, menubarY);
                peer.print(ng);
            } finally {
                ng.dispose();
            }
        }
    }

    public void setBoundsPrivate(int x, int y, int width, int height) {
        setBounds(x, y, width, height, SET_BOUNDS);
    }

    public Rectangle getBoundsPrivate() {
        return getBounds();
    }
}
