package com.jogamp.opengl.test.junit.jogl.awt;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.Rectangle;
import java.awt.ScrollPane;
import java.awt.Shape;
import java.io.IOException;

import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.WindowConstants;

import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;

import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;

/**
 * Documenting Bug 586
 * 
 * <p>
 * JScrollPane cannot mix hw/lw components, only if setting property '-Dsun.awt.disableMixing=true'.
 * </p>
 * <p>
 * You can use ScrollPane, or maybe a slider and fwd the panning to the GLCanvas,
 * which could change it's GL viewport accordingly.
 * </p>
 * See git commit '8df12ca151dfc577c90b485d4ebfe491b88e55aa'.
 */
public class TestJScrollPaneMixHwLw01AWT extends UITestCase {
    static long durationPerTest = 500;
    
    static {
        // too late: use at cmd-line '-Dsun.awt.disableMixing=true' works
        // System.setProperty("sun.awt.disableMixing", "true");
    }

    /**
     * Doesn't work either .. 
     */
    @SuppressWarnings("serial")
    public static class TransparentJScrollPane extends JScrollPane {

        public TransparentJScrollPane(Component view) {
            super(view);
    
            setOpaque(false);
       
            try {
                ReflectionUtil.callStaticMethod(
                                            "com.sun.awt.AWTUtilities", "setComponentMixingCutoutShape", 
                                            new Class<?>[] { Component.class, Shape.class }, 
                                            new Object[] { this, new Rectangle() } , 
                                            GraphicsConfiguration.class.getClassLoader());
                System.err.println("com.sun.awt.AWTUtilities.setComponentMixingCutoutShape(..) passed");
            } catch (RuntimeException re) {
                System.err.println("com.sun.awt.AWTUtilities.setComponentMixingCutoutShape(..) failed: "+re.getMessage());
            }
        }
    
        @Override
        public void setOpaque(boolean isOpaque) {
        }
    }
    
    protected void runTestGL(GLCapabilities caps, boolean useJScroll) throws InterruptedException {
        final JFrame frame = new JFrame("Mix Hw/Lw Swing");
        Assert.assertNotNull(frame);
        
        final Dimension f_sz = new Dimension(600,400);
        final Dimension glc_sz = new Dimension(500,600);
        
        final GLCanvas glCanvas = new GLCanvas(caps);
        Assert.assertNotNull(glCanvas);        
        glCanvas.addGLEventListener(new GearsES2());
        glCanvas.setPreferredSize(glc_sz);
        
        JPanel panel = new JPanel(new BorderLayout());
        panel.setOpaque(false);
        if(useJScroll) {
            final JScrollPane scrollPane = new TransparentJScrollPane(glCanvas);      
            panel.add(scrollPane, BorderLayout.CENTER);
        } else {
            ScrollPane scrollPane = new ScrollPane();
            scrollPane.add(glCanvas);
            panel.add(scrollPane, BorderLayout.CENTER);
        }
        
        JTextArea textArea = new JTextArea();
        textArea.setText("Test\nTest\nTest\nTest\n");

        panel.add(textArea, BorderLayout.NORTH);

        frame.add(panel);
        frame.setLocationRelativeTo(null);
        frame.setTitle("GLCanvas in JScrollPane example");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        try {
            javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
                public void run() {
                    frame.setSize(f_sz);
                    frame.setVisible(true);
                }});
        } catch (Throwable t) {
            t.printStackTrace();
            Assume.assumeNoException(t);
        }

        Animator animator = new Animator(glCanvas);
        animator.start();

        Thread.sleep(durationPerTest);

        animator.stop();
        
        try {
            javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
                public void run() {
                    frame.setVisible(false);
                    frame.dispose();
                }});
        } catch (Throwable t) {
            t.printStackTrace();
            Assume.assumeNoException(t);
        }
    }

    // @Test doesn't work
    public void test01JScrollPane() throws InterruptedException {
        GLProfile glp = GLProfile.getGL2ES2();
        GLCapabilities caps = new GLCapabilities(glp);
        runTestGL(caps, true);
    }

    @Test
    public void test01ScrollPane() throws InterruptedException {
        GLProfile glp = GLProfile.getGL2ES2();
        GLCapabilities caps = new GLCapabilities(glp);
        runTestGL(caps, false);
    }
    
    public static void main(String args[]) throws IOException {
        for(int i=0; i<args.length; i++) {
            if(args[i].equals("-time")) {
                durationPerTest = MiscUtils.atol(args[++i], durationPerTest);
            }
        }
        /**
        BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
        System.err.println("Press enter to continue");
        System.err.println(stdin.readLine()); 
        */
        System.out.println("durationPerTest: "+durationPerTest);
        String tstname = TestJScrollPaneMixHwLw01AWT.class.getName();
        org.junit.runner.JUnitCore.main(tstname);
    }
    
}
