/*
 * Copyright (c) 1997, 2010, 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.AWTPermission;
import java.awt.GraphicsDevice;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.DisplayMode;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.geom.Point2D;
import java.awt.image.ColorModel;
import java.util.ArrayList;
import java.util.Vector;
import java.awt.peer.WindowPeer;
import java.security.AccessController;
import sun.awt.windows.WWindowPeer;
import sun.java2d.SunGraphicsEnvironment;
import sun.java2d.opengl.WGLGraphicsConfig;
import sun.java2d.windows.WindowsFlags;
import sun.security.action.GetPropertyAction;
import static sun.awt.Win32GraphicsEnvironment.debugScaleX;
import static sun.awt.Win32GraphicsEnvironment.debugScaleY;

/**
 * This is an implementation of a GraphicsDevice object for a single
 * Win32 screen.
 *
 * @see GraphicsEnvironment
 * @see GraphicsConfiguration
 */
public class Win32GraphicsDevice extends GraphicsDevice implements
 DisplayChangedListener {
    int screen;
    ColorModel dynamicColorModel;   // updated with dev changes
    ColorModel colorModel;          // static for device
    protected GraphicsConfiguration[] configs;
    protected GraphicsConfiguration defaultConfig;

    private final String idString;
    protected String descString;
    // Note that we do not synchronize access to this variable - it doesn't
    // really matter if a thread does an operation on graphics device which is
    // about to become invalid (or already become) - we are prepared to deal
    // with this on the native level.
    private boolean valid;

    // keep track of top-level windows on this display
    private SunDisplayChanger topLevels = new SunDisplayChanger();
    // REMIND: we may disable the use of pixel formats for some accelerated
    // pipelines which are mutually exclusive with opengl, for which
    // pixel formats were added in the first place
    protected static boolean pfDisabled;
    private static AWTPermission fullScreenExclusivePermission;
    // the original display mode we had before entering the fullscreen
    // mode
    private DisplayMode defaultDisplayMode;
    // activation/deactivation listener for the full-screen window
    private WindowListener fsWindowListener;

    private float scaleX;
    private float scaleY;

    static {

        // 4455041 - Even when ddraw is disabled, ddraw.dll is loaded when
        // pixel format calls are made.  This causes problems when a Java app
        // is run as an NT service.  To prevent the loading of ddraw.dll
        // completely, sun.awt.nopixfmt should be set as well.  Apps which use
        // OpenGL w/ Java probably don't want to set this.
        String nopixfmt = (String)java.security.AccessController.doPrivileged(
            new sun.security.action.GetPropertyAction("sun.awt.nopixfmt"));
        pfDisabled = (nopixfmt != null);
        initIDs();
    }

    private static native void initIDs();

    native void initDevice(int screen);
    native void initNativeScale(int screen);
    native void setNativeScale(int screen, float scaleX, float scaleY);
    native float getNativeScaleX(int screen);
    native float getNativeScaleY(int screen);

    public Win32GraphicsDevice(int screennum) {
        this.screen = screennum;
        // we cache the strings because we want toString() and getIDstring
        // to reflect the original screen number (which may change if the
        // device is removed)
        idString = "\\Display"+screen;
        // REMIND: may be should use class name?
        descString = "Win32GraphicsDevice[screen=" + screen;
        valid = true;

        initDevice(screennum);
        initScaleFactors();
    }

    /**
     * Returns the type of the graphics device.
     * @see #TYPE_RASTER_SCREEN
     * @see #TYPE_PRINTER
     * @see #TYPE_IMAGE_BUFFER
     */
    public int getType() {
        return TYPE_RASTER_SCREEN;
    }

    /**
     * Returns the Win32 screen of the device.
     */
    public int getScreen() {
        return screen;
    }

    public float getDefaultScaleX() {
        return scaleX;
    }

    public float getDefaultScaleY() {
        return scaleY;
    }

    private void initScaleFactors() {
        if (SunGraphicsEnvironment.isUIScaleEnabled()) {
            if (debugScaleX > 0 && debugScaleY > 0) {
                scaleX = debugScaleX;
                scaleY = debugScaleY;
                setNativeScale(screen, scaleX, scaleY);
            } else {
                initNativeScale(screen);
                scaleX = getNativeScaleX(screen);
                scaleY = getNativeScaleY(screen);
            }
        } else {
            scaleX = 1;
            scaleY = 1;
        }
    }

    /**
     * Returns whether this is a valid devicie. Device can become
     * invalid as a result of device removal event.
     */
    public boolean isValid() {
        return valid;
    }

    /**
     * Called from native code when the device was removed.
     *
     * @param defaultScreen the current default screen
     */
    protected void invalidate(int defaultScreen) {
        valid = false;
        screen = defaultScreen;
    }

    /**
     * Returns the identification string associated with this graphics
     * device.
     */
    public String getIDstring() {
        return idString;
    }


    /**
     * Returns all of the graphics
     * configurations associated with this graphics device.
     */
    public GraphicsConfiguration[] getConfigurations() {
        if (configs==null) {
            if (WindowsFlags.isOGLEnabled() && isDefaultDevice()) {
                defaultConfig = getDefaultConfiguration();
                if (defaultConfig != null) {
                    configs = new GraphicsConfiguration[1];
                    configs[0] = defaultConfig;
                    return configs.clone();
                }
            }

            int max = getMaxConfigs(screen);
            int defaultPixID = getDefaultPixID(screen);
            Vector v = new Vector( max );
            if (defaultPixID == 0) {
                // Workaround for failing GDI calls
                defaultConfig = Win32GraphicsConfig.getConfig(this,
                                                              defaultPixID);
                v.addElement(defaultConfig);
            }
            else {
                for (int i = 1; i <= max; i++) {
                    if (isPixFmtSupported(i, screen)) {
                        if (i == defaultPixID) {
                            defaultConfig = Win32GraphicsConfig.getConfig(
                             this, i);
                            v.addElement(defaultConfig);
                        }
                        else {
                            v.addElement(Win32GraphicsConfig.getConfig(
                             this, i));
                        }
                    }
                }
            }
            configs = new GraphicsConfiguration[v.size()];
            v.copyInto(configs);
        }
        return configs.clone();
    }

    /**
     * Returns the maximum number of graphics configurations available, or 1
     * if PixelFormat calls fail or are disabled.
     * This number is less than or equal to the number of graphics
     * configurations supported.
     */
    protected int getMaxConfigs(int screen) {
        if (pfDisabled) {
            return 1;
        } else {
            return getMaxConfigsImpl(screen);
        }
    }

    private native int getMaxConfigsImpl(int screen);

    /**
     * Returns whether or not the PixelFormat indicated by index is
     * supported.  Supported PixelFormats support drawing to a Window
     * (PFD_DRAW_TO_WINDOW), support GDI (PFD_SUPPORT_GDI), and in the
     * case of an 8-bit format (cColorBits <= 8) uses indexed colors
     * (iPixelType == PFD_TYPE_COLORINDEX).
     * We use the index 0 to indicate that PixelFormat calls don't work, or
     * are disabled.  Do not call this function with an index of 0.
     * @param index a PixelFormat index
     */
    protected native boolean isPixFmtSupported(int index, int screen);

    /**
     * Returns the PixelFormatID of the default graphics configuration
     * associated with this graphics device, or 0 if PixelFormats calls fail or
     * are disabled.
     */
    protected int getDefaultPixID(int screen) {
        if (pfDisabled) {
            return 0;
        } else {
            return getDefaultPixIDImpl(screen);
        }
    }

    /**
     * Returns the default PixelFormat ID from GDI.  Do not call if PixelFormats
     * are disabled.
     */
    private native int getDefaultPixIDImpl(int screen);

    /**
     * Returns the default graphics configuration
     * associated with this graphics device.
     */
    public GraphicsConfiguration getDefaultConfiguration() {
        if (defaultConfig == null) {
            // first try to create a WGLGraphicsConfig if OGL is enabled
            // REMIND: the WGL code does not yet work properly in multimon
            // situations, so we will fallback on GDI if we are not on the
            // default device...
            if (WindowsFlags.isOGLEnabled() && isDefaultDevice()) {
                int defPixID = WGLGraphicsConfig.getDefaultPixFmt(screen);
                defaultConfig = WGLGraphicsConfig.getConfig(this, defPixID);
                if (WindowsFlags.isOGLVerbose()) {
                    if (defaultConfig != null) {
                        System.out.print("OpenGL pipeline enabled");
                    } else {
                        System.out.print("Could not enable OpenGL pipeline");
                    }
                    System.out.println(" for default config on screen " +
                                       screen);
                }
            }

            // Fix for 4669614.  Most apps are not concerned with PixelFormats,
            // yet we ALWAYS used them for determining ColorModels and such.
            // By passing in 0 as the PixelFormatID here, we signal that
            // PixelFormats should not be used, thus avoid loading the opengl
            // library.  Apps concerned with PixelFormats can still use
            // GraphicsConfiguration.getConfigurations().
            // Note that calling native pixel format functions tends to cause
            // problems between those functions (which are OpenGL-related)
            // and our use of DirectX.  For example, some Matrox boards will
            // crash or hang calling these functions when any app is running
            // in DirectX fullscreen mode.  So avoiding these calls unless
            // absolutely necessary is preferable.
            if (defaultConfig == null) {
                defaultConfig = Win32GraphicsConfig.getConfig(this, 0);
            }
        }
        return defaultConfig;
    }

    public String toString() {
        return valid ? descString + "]" : descString + ", removed]";
    }

    /**
     * Returns true if this is the default GraphicsDevice for the
     * GraphicsEnvironment.
     */
    private boolean isDefaultDevice() {
        return (this ==
                GraphicsEnvironment.
                    getLocalGraphicsEnvironment().getDefaultScreenDevice());
    }

    private static boolean isFSExclusiveModeAllowed() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            if (fullScreenExclusivePermission == null) {
                fullScreenExclusivePermission =
                    new AWTPermission("fullScreenExclusive");
            }
            try {
                security.checkPermission(fullScreenExclusivePermission);
            } catch (SecurityException e) {
                return false;
            }
        }
        return true;
    }

    /**
     * returns true unless we're not allowed to use fullscreen mode.
     */
    @Override
    public boolean isFullScreenSupported() {
        return isFSExclusiveModeAllowed();
    }

    @Override
    public synchronized void setFullScreenWindow(Window w) {
        Window old = getFullScreenWindow();
        if (w == old) {
            return;
        }
        if (!isFullScreenSupported()) {
            super.setFullScreenWindow(w);
            return;
        }

        // Enter windowed mode.
        if (old != null) {
            // restore the original display mode
            if (defaultDisplayMode != null) {
                setDisplayMode(defaultDisplayMode);
                // we set the default display mode to null here
                // because the default mode could change during
                // the life of the application (user can change it through
                // the desktop properties dialog, for example), so
                // we need to record it every time prior to
                // entering the fullscreen mode.
                defaultDisplayMode = null;
            }
            WWindowPeer peer = (WWindowPeer)old.getPeer();
            if (peer != null) {
                peer.setFullScreenExclusiveModeState(false);
                // we used to destroy the buffers on exiting fs mode, this
                // is no longer needed since fs change will cause a surface
                // data replacement
                synchronized(peer) {
                    exitFullScreenExclusive(screen, peer);
                }
            }
            removeFSWindowListener(old);
        }
        super.setFullScreenWindow(w);
        if (w != null) {
            // always record the default display mode prior to going
            // fullscreen
            defaultDisplayMode = getDisplayMode();
            addFSWindowListener(w);
            // Enter full screen exclusive mode.
            WWindowPeer peer = (WWindowPeer)w.getPeer();
            if (peer != null) {
                synchronized(peer) {
                    enterFullScreenExclusive(screen, peer);
                    // Note: removed replaceSurfaceData() call because
                    // changing the window size or making it visible
                    // will cause this anyway, and both of these events happen
                    // as part of switching into fullscreen mode.
                }
                peer.setFullScreenExclusiveModeState(true);
            }

            // fix for 4868278
            peer.updateGC();
        }
    }

    // Entering and exiting full-screen mode are done within a
    // tree-lock and should never lock on any resources which are
    // required by other threads which may have them and may require
    // the tree-lock.
    // REMIND: in the future these methods may need to become protected so that
    // subclasses could override them and use appropriate api other than GDI
    // for implementing these functions.
    protected native void enterFullScreenExclusive(int screen, WindowPeer w);
    protected native void exitFullScreenExclusive(int screen, WindowPeer w);

    @Override
    public boolean isDisplayChangeSupported() {
        return (isFullScreenSupported() && getFullScreenWindow() != null);
    }

    @Override
    public synchronized void setDisplayMode(DisplayMode dm) {
        if (!isDisplayChangeSupported()) {
            super.setDisplayMode(dm);
            return;
        }
        if (dm == null || (dm = getMatchingDisplayMode(dm)) == null) {
            throw new IllegalArgumentException("Invalid display mode");
        }
        if (getDisplayMode().equals(dm)) {
            return;
        }
        Window w = getFullScreenWindow();
        if (w != null) {
            WWindowPeer peer = (WWindowPeer)w.getPeer();
            configDisplayMode(screen, peer, dm.getWidth(), dm.getHeight(),
                dm.getBitDepth(), dm.getRefreshRate());
            // resize the fullscreen window to the dimensions of the new
            // display mode
            Rectangle screenBounds = getDefaultConfiguration().getBounds();
            w.setBounds(screenBounds.x, screenBounds.y,
                        dm.getWidth(), dm.getHeight());
            // Note: no call to replaceSurfaceData is required here since
            // replacement will be caused by an upcoming display change event
        } else {
            throw new IllegalStateException("Must be in fullscreen mode " +
                                            "in order to set display mode");
        }
    }

    protected native DisplayMode getCurrentDisplayMode(int screen);
    protected native void configDisplayMode(int screen, WindowPeer w, int width,
                                          int height, int bitDepth,
                                          int refreshRate);
    protected native void enumDisplayModes(int screen, ArrayList modes);

    @Override
    public synchronized DisplayMode getDisplayMode() {
        DisplayMode res = getCurrentDisplayMode(screen);
        return res;
    }

    @Override
    public synchronized DisplayMode[] getDisplayModes() {
        ArrayList modes = new ArrayList();
        enumDisplayModes(screen, modes);
        int listSize = modes.size();
        DisplayMode[] retArray = new DisplayMode[listSize];
        for (int i = 0; i < listSize; i++) {
            retArray[i] = (DisplayMode)modes.get(i);
        }
        return retArray;
    }

    protected synchronized DisplayMode getMatchingDisplayMode(DisplayMode dm) {
        if (!isDisplayChangeSupported()) {
            return null;
        }
        DisplayMode[] modes = getDisplayModes();
        for (DisplayMode mode : modes) {
            if (dm.equals(mode) ||
                (dm.getRefreshRate() == DisplayMode.REFRESH_RATE_UNKNOWN &&
                 dm.getWidth() == mode.getWidth() &&
                 dm.getHeight() == mode.getHeight() &&
                 dm.getBitDepth() == mode.getBitDepth()))
            {
                return mode;
            }
        }
        return null;
    }

    /*
     * From the DisplayChangeListener interface.
     * Called from Win32GraphicsEnvironment when the display settings have
     * changed.
     */
    public void displayChanged() {
        dynamicColorModel = null;
        defaultConfig = null;
        configs = null;
        // pass on to all top-level windows on this display
        initScaleFactors();
        topLevels.notifyListeners();
    }

    /**
     * Part of the DisplayChangedListener interface: devices
     * do not need to react to this event
     */
    public void paletteChanged() {
    }

    /*
     * Add a DisplayChangeListener to be notified when the display settings
     * are changed.  Typically, only top-level containers need to be added
     * to Win32GraphicsDevice.
     */
    public void addDisplayChangedListener(DisplayChangedListener client) {
        topLevels.add(client);
    }

    /*
     * Remove a DisplayChangeListener from this Win32GraphicsDevice
     */
     public void removeDisplayChangedListener(DisplayChangedListener client) {
        topLevels.remove(client);
    }

    /**
     * Creates and returns the color model associated with this device
     */
    private native ColorModel makeColorModel (int screen,
                                              boolean dynamic);

    /**
     * Returns a dynamic ColorModel which is updated when there
     * are any changes (e.g., palette changes) in the device
     */
    public ColorModel getDynamicColorModel() {
        if (dynamicColorModel == null) {
            dynamicColorModel = makeColorModel(screen, true);
        }
        return dynamicColorModel;
    }

    /**
     * Returns the non-dynamic ColorModel associated with this device
     */
    public ColorModel getColorModel() {
        if (colorModel == null)  {
            colorModel = makeColorModel(screen, false);
        }
        return colorModel;
    }

    /**
     * WindowAdapter class responsible for de/iconifying full-screen window
     * of this device.
     *
     * The listener restores the default display mode when window is iconified
     * and sets it back to the one set by the user on de-iconification.
     */
    private static class Win32FSWindowAdapter extends WindowAdapter {
        private Win32GraphicsDevice device;
        private DisplayMode dm;

        Win32FSWindowAdapter(Win32GraphicsDevice device) {
            this.device = device;
        }

        private void setFSWindowsState(Window other, int state) {
            GraphicsDevice gds[] =
                    GraphicsEnvironment.getLocalGraphicsEnvironment().
                    getScreenDevices();
            // check if the de/activation was caused by other
            // fs window and ignore the event if that's the case
            if (other != null) {
                for (GraphicsDevice gd : gds) {
                    if (other == gd.getFullScreenWindow()) {
                        return;
                    }
                }
            }
            // otherwise apply state to all fullscreen windows
            for (GraphicsDevice gd : gds) {
                Window fsw = gd.getFullScreenWindow();
                if (fsw instanceof Frame) {
                    ((Frame)fsw).setExtendedState(state);
                }
            }
        }

        @Override
        public void windowDeactivated(WindowEvent e) {
            setFSWindowsState(e.getOppositeWindow(), Frame.ICONIFIED);
        }

        @Override
        public void windowActivated(WindowEvent e) {
            setFSWindowsState(e.getOppositeWindow(), Frame.NORMAL);
        }

        @Override
        public void windowIconified(WindowEvent e) {
            // restore the default display mode for this device
            DisplayMode ddm = device.defaultDisplayMode;
            if (ddm != null) {
                dm = device.getDisplayMode();
                device.setDisplayMode(ddm);
            }
        }

        @Override
        public void windowDeiconified(WindowEvent e) {
            // restore the user-set display mode for this device
            if (dm != null) {
                device.setDisplayMode(dm);
                dm = null;
            }
        }
    }

    /**
     * Adds a WindowListener to be used as
     * activation/deactivation listener for the current full-screen window.
     *
     * @param w full-screen window
     */
    protected void addFSWindowListener(final Window w) {
        // Note: even though we create a listener for Window instances of
        // fs windows they will not receive window events.
        fsWindowListener = new Win32FSWindowAdapter(this);

        // Fix for 6709453. Using invokeLater to avoid listening
        // for the events already posted to the queue.
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                w.addWindowListener(fsWindowListener);
            }
        });
    }

    /**
     * Removes the fs window listener.
     *
     * @param w full-screen window
     */
    protected void removeFSWindowListener(Window w) {
        w.removeWindowListener(fsWindowListener);
        fsWindowListener = null;
    }
}
