/*
 * Copyright (c) 1997, 2025, 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.DisplayMode;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Window;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;

import sun.awt.image.SurfaceManager;
import sun.awt.util.ThreadGroupUtils;
import sun.java2d.SunGraphicsEnvironment;
import sun.java2d.loops.SurfaceType;
import sun.awt.X11.XToolkit;
import sun.java2d.opengl.GLXGraphicsConfig;
import sun.java2d.pipe.Region;
import sun.java2d.xr.XRGraphicsConfig;

/**
 * This is an implementation of a GraphicsDevice object for a single
 * X11 screen.
 *
 * @see GraphicsEnvironment
 * @see GraphicsConfiguration
 */
public final class X11GraphicsDevice extends GraphicsDevice
        implements DisplayChangedListener {
    /**
     * X11 screen number. This identifier can become non-valid at any time
     * therefore methods, which is using this id should be ready to it.
     */
    private volatile int screen;
    Map<SurfaceType, SurfaceManager.ProxyCache> x11ProxyCacheMap =
            Collections.synchronizedMap(new HashMap<>());

    private static Boolean xrandrExtSupported;
    private SunDisplayChanger topLevels = new SunDisplayChanger();
    private DisplayMode origDisplayMode;
    private volatile Rectangle bounds;
    private volatile Insets insets;
    private boolean shutdownHookRegistered;
    private int scale;

    // Wayland clients are by design not allowed to change the resolution in Wayland.
    // XRandR in Xwayland is just an emulation, it doesn't actually change the resolution.
    // This emulation is per window/x11 client, so different clients can have
    // different emulated resolutions at the same time.
    // So any request to get the current display mode will always return
    // the original screen resolution, even if we are in emulated resolution.
    // To handle this situation, we store the last set display mode in this variable.
    private volatile DisplayMode xwlCurrentDisplayMode;

    public X11GraphicsDevice(int screennum) {
        this.screen = screennum;
        this.scale = initScaleFactor();
        this.bounds = getBoundsImpl();
    }

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

    public SurfaceManager.ProxyCache getProxyCacheFor(SurfaceType st) {
        return x11ProxyCacheMap.computeIfAbsent(st,
                unused -> new SurfaceManager.ProxyCache());
    }

    /**
     * Returns the X11 Display of this device.
     * This method is also in MDrawingSurfaceInfo but need it here
     * to be able to allow a GraphicsConfigTemplate to get the Display.
     */
    public native long getDisplay();

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

    public int scaleUp(int x) {
        return Region.clipRound(x * (double)getScaleFactor());
    }

    public int scaleDown(int x) {
        return Region.clipRound(x / (double)getScaleFactor());
    }

    private Rectangle getBoundsImpl() {
        Rectangle rect = pGetBounds(getScreen());

        if (XToolkit.isOnWayland() && xwlCurrentDisplayMode != null) {
            // XRandR resolution change in Xwayland is an emulation,
            // and implemented in such a way that multiple display modes
            // for a device are only available in a single screen scenario,
            // if we have multiple screens they will each have a single display mode
            // (no emulated resolution change is available).
            // So we don't have to worry about x and y for a screen here.
            rect.setSize(
                    xwlCurrentDisplayMode.getWidth(),
                    xwlCurrentDisplayMode.getHeight()
            );
        }

        if (getScaleFactor() != 1) {
            rect.x = scaleDown(rect.x);
            rect.y = scaleDown(rect.y);
            rect.width = scaleDown(rect.width);
            rect.height = scaleDown(rect.height);
        }
        return rect;
    }

    public Rectangle getBounds() {
        return bounds.getBounds();
    }

    public Insets getInsets() {
        return insets;
    }

    public void setInsets(Insets newInsets) {
        Objects.requireNonNull(newInsets);
        insets = newInsets;
    }

    public void resetInsets() {
        insets = null;
    }

    /**
     * Returns the identification string associated with this graphics
     * device.
     */
    @Override
    public String getIDstring() {
        return ":0."+screen;
    }


    GraphicsConfiguration[] configs;
    GraphicsConfiguration defaultConfig;
    HashSet<Integer> doubleBufferVisuals;

    /**
     * Returns all of the graphics
     * configurations associated with this graphics device.
     */
    @Override
    public GraphicsConfiguration[] getConfigurations() {
        if (configs == null) {
            XToolkit.awtLock();
            try {
                makeConfigurations();
            } finally {
                XToolkit.awtUnlock();
            }
        }
        return configs.clone();
    }

    private void makeConfigurations() {
        if (configs == null) {
            int i = 1;  // Index 0 is always the default config
            int num = getNumConfigs(screen);
            GraphicsConfiguration[] ret = new GraphicsConfiguration[num];
            if (defaultConfig == null) {
                ret [0] = getDefaultConfiguration();
            }
            else {
                ret [0] = defaultConfig;
            }

            boolean glxSupported = X11GraphicsEnvironment.isGLXAvailable();
            boolean xrenderSupported = X11GraphicsEnvironment.isXRenderAvailable();

            boolean dbeSupported = isDBESupported();
            if (dbeSupported && doubleBufferVisuals == null) {
                doubleBufferVisuals = new HashSet<>();
                getDoubleBufferVisuals(screen);
            }
            for ( ; i < num; i++) {
                int visNum = getConfigVisualId(i, screen);
                int depth = getConfigDepth (i, screen);
                if (glxSupported) {
                    ret[i] = GLXGraphicsConfig.getConfig(this, visNum);
                }
                if (ret[i] == null) {
                    boolean doubleBuffer =
                        (dbeSupported &&
                         doubleBufferVisuals.contains(Integer.valueOf(visNum)));

                    if (xrenderSupported) {
                        ret[i] = XRGraphicsConfig.getConfig(this, visNum, depth,
                                getConfigColormap(i, screen), doubleBuffer);
                    } else {
                       ret[i] = X11GraphicsConfig.getConfig(this, visNum, depth,
                              getConfigColormap(i, screen),
                              doubleBuffer);
                    }
                }
            }
            configs = ret;
        }
    }

    /*
     * Returns the number of X11 visuals representable as an
     * X11GraphicsConfig object.
     */
    public native int getNumConfigs(int screen);

    /*
     * Returns the visualId for the given index of graphics configurations.
     */
    public native int getConfigVisualId (int index, int screen);
    /*
     * Returns the depth for the given index of graphics configurations.
     */
    private native int getConfigDepth(int index, int screen);

    /*
     * Returns the colormap for the given index of graphics configurations.
     */
    private native int getConfigColormap(int index, int screen);

    // Whether or not double-buffering extension is supported
    static native boolean isDBESupported();
    // Callback for adding a new double buffer visual into our set
    private void addDoubleBufferVisual(int visNum) {
        doubleBufferVisuals.add(Integer.valueOf(visNum));
    }
    // Enumerates all visuals that support double buffering
    private native void getDoubleBufferVisuals(int screen);

    /**
     * Returns the default graphics configuration
     * associated with this graphics device.
     */
    @Override
    public GraphicsConfiguration getDefaultConfiguration() {
        if (defaultConfig == null) {
            XToolkit.awtLock();
            try {
                makeDefaultConfiguration();
            } finally {
                XToolkit.awtUnlock();
            }
        }
        return defaultConfig;
    }

    private void makeDefaultConfiguration() {
        if (defaultConfig == null) {
            int visNum = getConfigVisualId(0, screen);
            if (X11GraphicsEnvironment.isGLXAvailable()) {
                defaultConfig = GLXGraphicsConfig.getConfig(this, visNum);
                if (X11GraphicsEnvironment.isGLXVerbose()) {
                    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);
                }
            }
            if (defaultConfig == null) {
                int depth = getConfigDepth(0, screen);
                boolean doubleBuffer = false;
                if (isDBESupported() && doubleBufferVisuals == null) {
                    doubleBufferVisuals = new HashSet<>();
                    getDoubleBufferVisuals(screen);
                    doubleBuffer =
                        doubleBufferVisuals.contains(Integer.valueOf(visNum));
                }

                if (X11GraphicsEnvironment.isXRenderAvailable()) {
                    if (X11GraphicsEnvironment.isXRenderVerbose()) {
                        System.out.println("XRender pipeline enabled");
                    }
                    defaultConfig = XRGraphicsConfig.getConfig(this, visNum,
                            depth, getConfigColormap(0, screen),
                            doubleBuffer);
                } else {
                    defaultConfig = X11GraphicsConfig.getConfig(this, visNum,
                                        depth, getConfigColormap(0, screen),
                                        doubleBuffer);
                }
            }
        }
    }

    private static native void enterFullScreenExclusive(long window);
    private static native void exitFullScreenExclusive(long window);
    private static native boolean initXrandrExtension(boolean useOldConfigDisplayMode);
    private static native DisplayMode getCurrentDisplayMode(int screen);
    private static native void enumDisplayModes(int screen,
                                                ArrayList<DisplayMode> modes);
    private static native void configDisplayMode(int screen,
                                                 int width, int height,
                                                 int displayMode);
    private static native double getNativeScaleFactor(int screen);
    private native Rectangle pGetBounds(int screenNum);

    /**
     * Returns true only if:
     *   - the Xrandr extension is present
     *   - the necessary Xrandr functions were loaded successfully
     */
    private static synchronized boolean isXrandrExtensionSupported() {
        if (xrandrExtSupported == null) {
            boolean useOldConfigDisplayMode =
                    Boolean.getBoolean("awt.x11useOldConfigDisplayMode");
            xrandrExtSupported = initXrandrExtension(useOldConfigDisplayMode);
        }
        return xrandrExtSupported;
    }

    @Override
    public boolean isFullScreenSupported() {
        return isXrandrExtensionSupported();
    }

    @Override
    public boolean isDisplayChangeSupported() {
        return (isFullScreenSupported()
                && (getFullScreenWindow() != null)
                && !((X11GraphicsEnvironment) GraphicsEnvironment
                        .getLocalGraphicsEnvironment()).runningXinerama());
    }

    private static void enterFullScreenExclusive(Window w) {
        X11ComponentPeer peer = AWTAccessor.getComponentAccessor().getPeer(w);
        if (peer != null) {
            enterFullScreenExclusive(peer.getWindow());
            peer.setFullScreenExclusiveModeState(true);
        }
    }

    private static void exitFullScreenExclusive(Window w) {
        X11ComponentPeer peer = AWTAccessor.getComponentAccessor().getPeer(w);
        if (peer != null) {
            peer.setFullScreenExclusiveModeState(false);
            exitFullScreenExclusive(peer.getWindow());
        }
    }

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

        boolean fsSupported = isFullScreenSupported();
        if (fsSupported && old != null) {
            // enter windowed mode (and restore original display mode)
            exitFullScreenExclusive(old);
            if (isDisplayChangeSupported()) {
                setDisplayMode(origDisplayMode);
            }
        }

        super.setFullScreenWindow(w);

        if (fsSupported && w != null) {
            // save original display mode
            if (origDisplayMode == null) {
                origDisplayMode = getDisplayMode();
            }

            // enter fullscreen mode
            enterFullScreenExclusive(w);
        }
    }

    private DisplayMode getDefaultDisplayMode() {
        GraphicsConfiguration gc = getDefaultConfiguration();
        Rectangle r = gc.getBounds();
        return new DisplayMode(r.width, r.height,
                               DisplayMode.BIT_DEPTH_MULTI,
                               DisplayMode.REFRESH_RATE_UNKNOWN);
    }

    @Override
    public synchronized DisplayMode getDisplayMode() {
        if (isFullScreenSupported()) {
            if (XToolkit.isOnWayland() && xwlCurrentDisplayMode != null) {
                return xwlCurrentDisplayMode;
            }

            DisplayMode mode = getCurrentDisplayMode(screen);
            if (mode == null) {
                mode = getDefaultDisplayMode();
            }

            if (XToolkit.isOnWayland()) {
                xwlCurrentDisplayMode = mode;
            }

            return mode;
        } else {
            if (origDisplayMode == null) {
                origDisplayMode = getDefaultDisplayMode();
            }
            return origDisplayMode;
        }
    }

    @Override
    public synchronized DisplayMode[] getDisplayModes() {
        if (!isFullScreenSupported()
                || ((X11GraphicsEnvironment) GraphicsEnvironment
                            .getLocalGraphicsEnvironment()).runningXinerama()) {
            // only the current mode will be returned
            return super.getDisplayModes();
        }
        ArrayList<DisplayMode> modes = new ArrayList<DisplayMode>();
        enumDisplayModes(screen, modes);
        DisplayMode[] retArray = new DisplayMode[modes.size()];
        return modes.toArray(retArray);
    }

    @Override
    public synchronized void setDisplayMode(DisplayMode dm) {
        if (!isDisplayChangeSupported()) {
            super.setDisplayMode(dm);
            return;
        }
        Window w = getFullScreenWindow();
        if (w == null) {
            throw new IllegalStateException("Must be in fullscreen mode " +
                                            "in order to set display mode");
        }
        if (getDisplayMode().equals(dm)) {
            return;
        }
        if (dm == null ||
            (dm = getMatchingDisplayMode(dm)) == null)
        {
            throw new IllegalArgumentException("Invalid display mode");
        }

        if (!shutdownHookRegistered) {
            // register a shutdown hook so that we return to the
            // original DisplayMode when the VM exits (if the application
            // is already in the original DisplayMode at that time, this
            // hook will have no effect)
            shutdownHookRegistered = true;
            Runnable r = () -> {
                Window old = getFullScreenWindow();
                if (old != null) {
                    exitFullScreenExclusive(old);
                    if (isDisplayChangeSupported()) {
                        setDisplayMode(origDisplayMode);
                    }
                }
            };
            String name = "Display-Change-Shutdown-Thread-" + screen;
            Thread t = new Thread(
                  ThreadGroupUtils.getRootThreadGroup(), r, name, 0, false);
            t.setContextClassLoader(null);
            Runtime.getRuntime().addShutdownHook(t);
        }

        // switch to the new DisplayMode
        configDisplayMode(screen,
                          dm.getWidth(), dm.getHeight(),
                          dm.getRefreshRate());

        if (XToolkit.isOnWayland()) {
            xwlCurrentDisplayMode = dm;
        }

        // update bounds of the fullscreen window
        w.setBounds(0, 0, dm.getWidth(), dm.getHeight());

        // configDisplayMode() is synchronous, so the display change will be
        // complete by the time we get here (and it is therefore safe to call
        // displayChanged() now)
        ((X11GraphicsEnvironment)
         GraphicsEnvironment.getLocalGraphicsEnvironment()).displayChanged();
    }

    private 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 DisplayChangedListener interface; called from
     * X11GraphicsEnvironment when the display mode has been changed.
     */
    @Override
    public synchronized void displayChanged() {
        scale = initScaleFactor();
        bounds = getBoundsImpl();
        insets = null;
        // On X11 the visuals do not change, and therefore we don't need
        // to reset the defaultConfig, config, doubleBufferVisuals,
        // neither do we need to reset the native data.

        // pass on to all top-level windows on this screen
        topLevels.notifyListeners();
    }

    /**
     * From the DisplayChangedListener interface; devices do not need
     * to react to this event.
     */
    @Override
    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 X11GraphicsDevice.
     */
    public void addDisplayChangedListener(DisplayChangedListener client) {
        topLevels.add(client);
    }

    public int getScaleFactor() {
        return scale;
    }

    public int getNativeScale() {
        return (int)Math.round(getNativeScaleFactor(screen));
    }

    private int initScaleFactor() {

        if (SunGraphicsEnvironment.isUIScaleEnabled()) {

            double debugScale = SunGraphicsEnvironment.getDebugScale();

            if (debugScale >= 1) {
                return (int) debugScale;
            }
            int nativeScale = getNativeScale();
            return nativeScale >= 1 ? nativeScale : 1;
        }

        return 1;
    }

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

    @Override
    public String toString() {
        return ("X11GraphicsDevice[screen="+screen+"]");
    }

    public void invalidate(X11GraphicsDevice device) {
        assert XToolkit.isAWTLockHeldByCurrentThread();

        screen = device.screen;
    }
}
