/*
 * Copyright (c) 2005, 2014 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.
 *
 * 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.
 */

/*
 @test
 @key headful
 @bug 6275887 6429971 6459792
 @summary Test that we don't crash when alt+tabbing in and out of
         fullscreen app
 @author Dmitri.Trembovetski@sun.com: area=FullScreen
 @run main/othervm/timeout=100  AltTabCrashTest -auto -changedm
 @run main/othervm/timeout=100 -Dsun.java2d.d3d=True AltTabCrashTest -auto -changedm
 @run main/othervm/timeout=100 -Dsun.java2d.d3d=True AltTabCrashTest -auto -usebs -changedm
 @run main/othervm/timeout=100 -Dsun.java2d.opengl=True AltTabCrashTest -auto
*/

import java.awt.AWTException;
import java.awt.Color;
import java.awt.DisplayMode;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Robot;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
import java.util.Random;
import java.util.Vector;

/**
 * Note that the alt+tabbing in and out part will most likely only work
 * on Windows, and only if there are no interventions.
 */

public class AltTabCrashTest extends Frame {
    public static int width;
    public static int height;
    public static volatile boolean autoMode;
    public static boolean useBS;
    public static final int NUM_OF_BALLS = 70;
    // number of times to alt+tab in and out of the app
    public static int altTabs = 5;
    private final Vector<Ball> balls = new Vector<>();
    GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment()
        .getDefaultScreenDevice();
    VolatileImage vimg = null;
    BufferStrategy bufferStrategy = null;
    volatile boolean timeToQuit = false;
    static final Object lock = new Object();

    enum SpriteType {
        OVALS, VIMAGES, BIMAGES, AAOVALS, TEXT
    }

    private static boolean changeDM = false;
    private static SpriteType spriteType;
    static Random rnd = new Random();

    public AltTabCrashTest( ) {
        addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
                    timeToQuit = true;
                }
            }
        });
        setIgnoreRepaint(true);
        addMouseListener(new MouseHandler());
        for (int i = 0; i < NUM_OF_BALLS; i++) {
            int x = 50 + rnd.nextInt(550), y = 50 + rnd.nextInt(400);

            balls.addElement(createRandomBall(y, x));
        }
        setUndecorated(true);
        gd.setFullScreenWindow(this);
        GraphicsDevice gd = getGraphicsConfiguration().getDevice();
        if (gd.isDisplayChangeSupported() && changeDM) {
            DisplayMode dm = findDisplayMode();
            if (dm != null) {
                try {
                    gd.setDisplayMode(dm);
                } catch (IllegalArgumentException iae) {
                    System.err.println("Error setting display mode");
                }
            }
        }
        if (useBS) {
            createBufferStrategy(2);
            bufferStrategy = getBufferStrategy();
        } else {
            Graphics2D g = (Graphics2D) getGraphics();
            render(g);
            g.dispose();
        }
        Thread t = new BallThread();
        t.start();
        if (autoMode) {
            Thread tt = new AltTabberThread();
            tt.start();
            synchronized (lock) {
                while (!timeToQuit) {
                    try {
                        lock.wait(200);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
            }
            t = null;
            dispose();
        }
    }

    private Ball createRandomBall(final int y, final int x) {
        Ball b;
        SpriteType type;

        if (spriteType == null) {
            int index = rnd.nextInt(SpriteType.values().length);
            type = SpriteType.values()[index];
        } else {
            type = spriteType;
        }
        switch (type) {
            case VIMAGES: b = new VISpriteBall(x, y); break;
            case AAOVALS: b = new AAOvalBall(x, y); break;
            case BIMAGES: b = new BISpriteBall(x, y); break;
            case TEXT: b = new TextBall(x,y, "Text Sprite!"); break;
            default: b = new Ball(x, y); break;
        }
        return b;
    }

    private class MouseHandler extends MouseAdapter  {
        public void mousePressed(MouseEvent e) {
            synchronized (balls) {
                balls.addElement(createRandomBall(e.getX(), e.getY()));
            }
        }
    }

    private class AltTabberThread extends Thread {
        Robot robot;

        void pressAltTab() {
            robot.keyPress(KeyEvent.VK_ALT);
            robot.keyPress(KeyEvent.VK_TAB);
            robot.keyRelease(KeyEvent.VK_TAB);
            robot.keyRelease(KeyEvent.VK_ALT);
        }
        void pressShiftAltTab() {
            robot.keyPress(KeyEvent.VK_SHIFT);
            pressAltTab();
            robot.keyRelease(KeyEvent.VK_SHIFT);
        }
        public void run() {
            try {
                robot = new Robot();
                robot.setAutoDelay(200);
            } catch (AWTException e) {
                throw new RuntimeException("Can't create robot");
            }
            boolean out = true;
            while (altTabs-- > 0 && !timeToQuit) {
                System.err.println("Alt+tabber Iteration: "+altTabs);
                try { Thread.sleep(2500); } catch (InterruptedException ex) {}

                if (out) {
                    System.err.println("Issuing alt+tab");
                    pressAltTab();
                } else {
                    System.err.println("Issuing shift ");
                    pressShiftAltTab();
                }
                out = !out;
            }
            System.err.println("Alt+tabber finished.");
            synchronized (lock) {
                timeToQuit = true;
                lock.notify();
            }
        }
    }

    private class BallThread extends Thread {
        public void run() {
            while (!timeToQuit) {
                if (useBS) {
                    renderToBS();
                    bufferStrategy.show();
                } else {
                    Graphics g = AltTabCrashTest.this.getGraphics();
                    render(g);
                    g.dispose();
                }
            }
            gd.setFullScreenWindow(null);
            AltTabCrashTest.this.dispose();
        }
    }

    static class Ball {

        int x, y;     // current location
        int dx, dy;   // motion delta
        int diameter = 40;
        Color color = Color.red;

        public Ball() {
        }

        public Ball(int x, int y) {
            this.x = x;
            this.y = y;
            dx = x % 20 + 1;
            dy = y % 20 + 1;
            color = new Color(rnd.nextInt(0x00ffffff));
        }

        public void move() {
            if (x < 10 || x >= AltTabCrashTest.width - 20)
                dx = -dx;
            if (y < 10 || y > AltTabCrashTest.height - 20)
                dy = -dy;
            x += dx;
            y += dy;
        }

        public void paint(Graphics g, Color c) {
            if (c == null) {
                g.setColor(color);
            } else {
                g.setColor(c);
            }
            g.fillOval(x, y, diameter, diameter);
        }

    }

    static class TextBall extends Ball {
        String text;
        public TextBall(int x, int y, String text) {
            super(x, y);
            this.text = text;
        }

        public void paint(Graphics g, Color c) {
            if (c == null) {
                g.setColor(color);
            } else {
                g.setColor(c);
            }
            g.drawString(text, x, y);
        }
    }

    static class AAOvalBall extends Ball {
        public AAOvalBall(int x, int y) {
            super(x, y);
        }
        public void paint(Graphics g, Color c) {
            if (c == null) {
                Graphics2D g2d = (Graphics2D)g.create();
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                     RenderingHints.VALUE_ANTIALIAS_ON);
                g2d.setColor(color);
                g2d.fillOval(x, y, diameter, diameter);
            } else {
                g.setColor(c);
                g.fillOval(x-2, y-2, diameter+4, diameter+4);
            }
        }
    }

    static abstract class SpriteBall extends Ball {
        Image image;
        public SpriteBall(int x, int y) {
            super(x, y);
            image = createSprite();
            Graphics g = image.getGraphics();
            g.setColor(color);
            g.fillRect(0, 0, image.getWidth(null), image.getHeight(null));
        }
        public void paint(Graphics g, Color c) {
            if (c != null) {
                g.setColor(c);
                g.fillRect(x, y, image.getWidth(null), image.getHeight(null));
            } else do {
                validateSprite();
                g.drawImage(image, x, y, null);
            } while (renderingIncomplete());
        }
        public abstract Image createSprite();
        public void validateSprite() {}
        public boolean renderingIncomplete() { return false; }
    }
    class VISpriteBall extends SpriteBall {

        public VISpriteBall(int x, int y) {
            super(x, y);
        }
        public boolean renderingIncomplete() {
            return ((VolatileImage)image).contentsLost();
        }

        public Image createSprite() {
            return gd.getDefaultConfiguration().
                createCompatibleVolatileImage(20, 20);
        }
        public void validateSprite() {
            int result =
                ((VolatileImage)image).validate(getGraphicsConfiguration());
            if (result == VolatileImage.IMAGE_INCOMPATIBLE) {
                image = createSprite();
                result = VolatileImage.IMAGE_RESTORED;
            }
            if (result == VolatileImage.IMAGE_RESTORED) {
                Graphics g = image.getGraphics();
                g.setColor(color);
                g.fillRect(0, 0, image.getWidth(null), image.getHeight(null));
            }
        }
    }
    class BISpriteBall extends SpriteBall {
        public BISpriteBall(int x, int y) {
            super(x, y);
        }
        public Image createSprite() {
            return new BufferedImage(20, 20, BufferedImage.TYPE_INT_RGB);
        }
    }


    public void renderOffscreen() {
        Graphics2D g2d = (Graphics2D) vimg.getGraphics();
        synchronized (balls) {
            for (Ball b : balls) {
                b.paint(g2d, getBackground());
                b.move();
                b.paint(g2d, null);
            }
        }
        g2d.dispose();
    }

    public void renderToBS() {
        width = getWidth();
        height = getHeight();

        do {
            Graphics2D g2d = (Graphics2D)bufferStrategy.getDrawGraphics();

            g2d.clearRect(0, 0, width, height);
            synchronized (balls) {
                for (Ball b : balls) {
                    b.move();
                    b.paint(g2d, null);
                }
            }
            g2d.dispose();
        } while (bufferStrategy.contentsLost() ||
                bufferStrategy.contentsRestored());
    }

    public void render(Graphics g)  {
        do {
            height = getBounds().height;
            width = getBounds().width;
            if (vimg == null) {
                vimg = createVolatileImage(width, height);
                renderOffscreen();
            }
            int returnCode = vimg.validate(getGraphicsConfiguration());
            if (returnCode == VolatileImage.IMAGE_RESTORED) {
                renderOffscreen();
            } else if (returnCode == VolatileImage.IMAGE_INCOMPATIBLE) {
                vimg = getGraphicsConfiguration().
                    createCompatibleVolatileImage(width, height);
                renderOffscreen();
            } else if (returnCode == VolatileImage.IMAGE_OK) {
                renderOffscreen();
            }
            g.drawImage(vimg, 0, 0, this);
        } while (vimg.contentsLost());
    }

    public static void main(String args[])  {
        for (String arg : args) {
            if (arg.equalsIgnoreCase("-auto")) {
                autoMode = true;
                System.err.println("Running in automatic mode using Robot");
            } else if (arg.equalsIgnoreCase("-usebs")) {
                useBS = true;
                System.err.println("Using BufferStrategy instead of VI");
            } else if (arg.equalsIgnoreCase("-changedm")) {
                changeDM= true;
                System.err.println("The test will change display mode");
            } else if (arg.equalsIgnoreCase("-vi")) {
                spriteType = SpriteType.VIMAGES;
            } else if (arg.equalsIgnoreCase("-bi")) {
                spriteType = SpriteType.BIMAGES;
            } else if (arg.equalsIgnoreCase("-ov")) {
                spriteType = SpriteType.OVALS;
            } else if (arg.equalsIgnoreCase("-aaov")) {
                spriteType = SpriteType.AAOVALS;
            } else if (arg.equalsIgnoreCase("-tx")) {
                spriteType = SpriteType.TEXT;
            } else {
                System.err.println("Usage: AltTabCrashTest [-usebs][-auto]" +
                                   "[-changedm][-vi|-bi|-ov|-aaov|-tx]");
                System.err.println(" -usebs: use BufferStrategy instead of VI");
                System.err.println(" -auto: automatically alt+tab in and out" +
                                   " of the application ");
                System.err.println(" -changedm: change display mode");
                System.err.println(" -(vi|bi|ov|tx|aaov) : use only VI, BI, " +
                                   "text or [AA] [draw]Oval sprites");
                System.exit(0);
            }
        }
        if (spriteType != null) {
            System.err.println("The test will only use "+spriteType+" sprites.");
        }
        new AltTabCrashTest();
    }

    private DisplayMode findDisplayMode() {
        GraphicsDevice gd = getGraphicsConfiguration().getDevice();
        DisplayMode dms[] = gd.getDisplayModes();
        DisplayMode currentDM = gd.getDisplayMode();
        for (DisplayMode dm : dms) {
            if (dm.getBitDepth() > 8 &&
                dm.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI &&
                dm.getBitDepth() != currentDM.getBitDepth() &&
                dm.getWidth() == currentDM.getWidth() &&
                dm.getHeight() == currentDM.getHeight())
            {
                // found a mode which has the same dimensions but different
                // depth
                return dm;
            }
            if (dm.getBitDepth() == DisplayMode.BIT_DEPTH_MULTI &&
                (dm.getWidth() != currentDM.getWidth() ||
                 dm.getHeight() != currentDM.getHeight()))
            {
                // found a mode which has the same depth but different
                // dimensions
                return dm;
            }
        }

        return null;
    }
}
