/**
 * Copyright (c) 2008-2014 Ardor Labs, Inc.
 *
 * This file is part of Ardor3D.
 *
 * Ardor3D is free software: you can redistribute it and/or modify it
 * under the terms of its license which may be found in the accompanying
 * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
 */

package com.ardor3d.example.canvas;

import com.ardor3d.example.GameThread;
import com.ardor3d.example.MyThread;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.net.URISyntaxException;
import javax.swing.JFrame;
import javax.swing.JPopupMenu;

import com.ardor3d.example.Purpose;
import com.ardor3d.framework.DisplaySettings;
import com.ardor3d.framework.FrameHandler;
import com.ardor3d.framework.jogl.JoglCanvasRenderer;
import com.ardor3d.framework.jogl.awt.JoglAwtCanvas;
import com.ardor3d.framework.jogl.awt.JoglNewtAwtCanvas;
import com.ardor3d.framework.jogl.awt.JoglSwingCanvas;
import com.ardor3d.image.util.awt.AWTImageLoader;
import com.ardor3d.input.ControllerWrapper;
import com.ardor3d.input.Key;
import com.ardor3d.input.PhysicalLayer;
import com.ardor3d.input.awt.AwtFocusWrapper;
import com.ardor3d.input.awt.AwtKeyboardWrapper;
import com.ardor3d.input.awt.AwtMouseManager;
import com.ardor3d.input.awt.AwtMouseWrapper;
import com.ardor3d.input.jogl.JoglNewtFocusWrapper;
import com.ardor3d.input.jogl.JoglNewtKeyboardWrapper;
import com.ardor3d.input.jogl.JoglNewtMouseManager;
import com.ardor3d.input.jogl.JoglNewtMouseWrapper;
import com.ardor3d.input.logical.DummyControllerWrapper;
import com.ardor3d.input.logical.LogicalLayer;
import com.ardor3d.renderer.Camera;
import com.ardor3d.util.GameTaskQueueManager;
import com.ardor3d.util.Timer;
import com.ardor3d.util.resource.ResourceLocatorTool;
import com.ardor3d.util.resource.SimpleResourceLocator;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JDesktopPane;
import javax.swing.JInternalFrame;

/**
 * This examples demonstrates how to render OpenGL (via JOGL) inside JDesktop internal frames.
 */
@Purpose(htmlDescriptionKey = "com.ardor3d.example.canvas.JoglAwtDesktopExample", //
thumbnailPath = "com/ardor3d/example/media/thumbnails/canvas_JoglAwtDesktopExample.jpg", //
maxHeapMemory = 64)

public class JDesktopTest {

    public static void main(final String[] args) throws Exception {
        GameTaskQueueManager qmanager1 = GameTaskQueueManager.getManager("Example1");
        GameTaskQueueManager qmanager2 = GameTaskQueueManager.getManager("Example2");
        GameTaskQueueManager qmanager3 = GameTaskQueueManager.getManager("Example3");
        
        System.setProperty("ardor3d.useMultipleContexts", "true");
        JPopupMenu.setDefaultLightWeightPopupEnabled(false);
 
        //----- resource for texture image
        AWTImageLoader.registerLoader();
        try {
            final SimpleResourceLocator srl = new SimpleResourceLocator(ResourceLocatorTool.getClassPathResource(
                    JoglAwtDesktopExample.class, "com/ardor3d/example/media/"));
            ResourceLocatorTool.addResourceLocator(ResourceLocatorTool.TYPE_TEXTURE, srl);
        } catch (final URISyntaxException ex) {
            ex.printStackTrace();
        }
        final AWTImageLoader awtImageLoader = new AWTImageLoader();
        
        
        final MyExit exit = new MyExit();
        
        final JFrame frame = new JFrame("JDesktop Example");
        final JDesktopPane desktop = new JDesktopPane();
        frame.setContentPane(desktop);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(final WindowEvent e) {
                exit.exit();
            }
        });
        frame.setPreferredSize(new Dimension(1024, 768));
        frame.pack();
        frame.setVisible(true);
        
        
        // Setup the master FrameHandler and start the runner thread

        final Timer timer = new Timer();
        final FrameHandler frameWork = new FrameHandler(timer);
        final LogicalLayer logicalLayer = new LogicalLayer();
        
        MyThread runner = new MyThread(frameWork);
        runner.start();
        
        // make first scene for first internal frame.

        final MyScene scene1 = new MyScene(qmanager1);
        final RotatingCube game1 = new RotatingCube(scene1, exit, logicalLayer, Key.T, qmanager1);
        //game1.addCube();
        JoglAwtCanvas canvas1 = addCanvas(desktop, scene1, logicalLayer, frameWork, 1);
        /*---- Let Ardor initialize
          canvas.init();
        */
        frameWork.addUpdater(game1);
        frameWork.addCanvas(canvas1);
        game1.addCube2();
        
        // wait 5 secs, add a new internal frame
        
        try {
          java.lang.Thread.sleep(5000);
        }
        catch (Exception e) {
        }
        

        final MyScene scene2 = new MyScene(qmanager2);
        final RotatingCube game2 = new RotatingCube(scene2, exit, logicalLayer, Key.G, qmanager2);
        //game2.addCube();
        JoglAwtCanvas canvas2 = addCanvas(desktop, scene2, logicalLayer, frameWork, 2);
        /*---- Let Ardor initialize
          canvas.init();
        */
        frameWork.addUpdater(game2);
        frameWork.addCanvas(canvas2);
        
    
        try {
          java.lang.Thread.sleep(4000);
        }
        catch (Exception e) {
        }
        
        class AppThread implements Runnable {
           public void run() {

              game1.addCube2();
              game2.addCube2();
           }
        }
        Thread appThread = new Thread(new AppThread());
        appThread.start();
        
        
        try {
          java.lang.Thread.sleep(5000);
        }
        catch (Exception e) {
        }
        
        final MyScene scene3 = new MyScene(qmanager3);
        final RotatingCube game3 = new RotatingCube(scene3, exit, logicalLayer, Key.G, qmanager3);
        
        //game3.addCube();
        JoglAwtCanvas canvas3 = addCanvas(desktop, scene3, logicalLayer, frameWork, 3);
        frameWork.addUpdater(game3);
        frameWork.addCanvas(canvas3);
        game3.addCube2();

    }

    private static JoglAwtCanvas addCanvas(final JDesktopPane desktop, final MyScene scene,
            final LogicalLayer logicalLayer, final FrameHandler frameWork, final int index) throws Exception {
        final JInternalFrame frame = new JInternalFrame(String.valueOf(index), true, true, true, true);
        frame.setSize(400,300);
        frame.setVisible(true);
        
        final JoglCanvasRenderer canvasRenderer = new JoglCanvasRenderer(scene);
        final DisplaySettings settings = new DisplaySettings(400, 300, 24, 0, 0, 16, 0, 0, false, false);
        final JoglAwtCanvas theCanvas = new JoglAwtCanvas(settings, canvasRenderer);


        final AwtKeyboardWrapper keyboardWrapper = new AwtKeyboardWrapper(theCanvas);
        final AwtFocusWrapper focusWrapper = new AwtFocusWrapper(theCanvas);
        final AwtMouseManager mouseManager = new AwtMouseManager(theCanvas);
        final AwtMouseWrapper mouseWrapper = new AwtMouseWrapper(theCanvas, mouseManager);
        
        theCanvas.setMouseManager(mouseManager);
        final ControllerWrapper controllerWrapper = new DummyControllerWrapper();

        final PhysicalLayer pl = new PhysicalLayer(keyboardWrapper, mouseWrapper, controllerWrapper, focusWrapper);

        logicalLayer.registerInput(theCanvas, pl);

        
        frame.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(final ComponentEvent e) {
                final Camera cam = theCanvas.getCanvasRenderer().getCamera();
                if (cam != null) {
                    cam.resize(theCanvas.getWidth(), theCanvas.getHeight());
                    cam.setFrustumPerspective(cam.getFovY(), theCanvas.getWidth() / (float) theCanvas.getHeight(),
                            cam.getFrustumNear(), cam.getFrustumFar());
                }
            }
        });
        
        frame.setLocation(20 * index, 20 * index);
        frame.add(theCanvas);
        frame.pack();
        frame.setVisible(true);
        desktop.add(frame);
        
        return theCanvas;
    }

    private static class MyExit implements Exit {
        private volatile boolean exit = false;

        @Override
        public void exit() {
            exit = true;
        }

        public boolean isExit() {
            return exit;
        }
    }
}