/*
 *      @(#)Vrml97Player.java 1.30 98/11/05 20:47:24
 *
 * Copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.

 * @Author: Rick Goldberg
 * @Author: Doug Gehringer
 */


// A Frame which creates a Canvas3D and a Browser and passes a URL to
// the browser to be loaded

// TODO: make into an applet
import java.awt.*;
import java.awt.Image.*;
import java.awt.image.BufferedImage ;
import java.awt.event.*;
import java.io.*;
import java.io.File;
import java.io.IOException;
import java.awt.Window;
import java.awt.Frame;
import java.awt.FileDialog;
import java.awt.MenuBar;
import java.awt.Menu;
import java.awt.MenuItem;
import java.awt.Cursor;
import java.awt.FlowLayout;
import java.awt.BorderLayout;
import java.awt.Panel;
import java.awt.Label;
import java.awt.Event;
import java.awt.TextField;
import java.awt.AWTEvent;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.WindowListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Enumeration;
import javax.vecmath.*;
import javax.media.j3d.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.GraphicsContext3D;
import javax.media.j3d.Canvas3D;
import vrml.Browser;
import com.sun.*;
import com.sun.image.codec.jpeg.*;
import com.sun.j3d.loaders.vrml97.Player;
import ViewSourceFrame;


public class Vrml97Player extends Frame  implements ActionListener, Runnable, Player {

    MenuBar mb;
    Menu m;
    MenuItem mi;
    Button snap = new Button ("snapshot");

    static Vrml97Player v97p ;
    Canvas3D canvas;
    GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
    Raster rasSnapshot;
    boolean bTakeSnapshot ;
    String[]   urlString;
    Browser  browser;
    TextField gotoWrl;
    Panel panel;
    PrintWriter ecrivain;
    Label label;
    FileDialog fd;
    String filename;
    String pathname;
    File file;
    ViewSourceFrame f;
    boolean firstTime = true;
    WindowListener wl;
    Menu vpMenu;
    String[] vpDesc = null;
    String vpAction = "setVp ";
    ComponentListener cl;
    String resetVp = "Reset Viewpoint";
    public static Thread sync;
    static int h=780,w=780;
    // note these are window system specific
    static final int H = 105;
    static final int W = 10;


    Vrml97Player(String initURL) {
	urlString = new String[1];
	urlString[0] = initURL;



	int lastSlash = 0;
	if (!urlString[0].endsWith(".wrl") && !urlString[0].endsWith("z")) {
    pathname = urlString[0];
	    urlString[0]+="interp.wrl";
	} else {
	    lastSlash = urlString[0].lastIndexOf("/");
	    if (lastSlash < 1) {
		lastSlash = urlString[0].lastIndexOf("\\");
	    }
	    pathname =  urlString[0].substring(0,lastSlash+1);
	}

	// menus
	mb = new MenuBar();
	m = new Menu("File");
	mi = new MenuItem("Open");
	mi.addActionListener(this);
	m.add(mi);
	mi = new MenuItem("Suspend");
	mi.addActionListener(this);
	m.add(mi);
	mi = new MenuItem("Resume");
	mi.addActionListener(this);
	m.add(mi);
	mi = new MenuItem("Exit");
	mi.addActionListener(this);
	m.add(mi);
	mb.add(m);


	m = new Menu("View");
	vpMenu = new Menu("Select Viewpoint");
	m.add(vpMenu);
	mi = new MenuItem(resetVp);
	mi.addActionListener(this);
	m.add(mi);
	mi = new MenuItem("WorldInfo");
	mi.addActionListener(this);
	m.add(mi);
	mi = new MenuItem("View/Edit Source");
	mi.addActionListener(this);
	m.add(mi);
	mb.add(m);

	m = new Menu("Info");
	mi = new MenuItem("About");
	mi.addActionListener(this);
	m.add(mi);
	mb.add(m);

      m = new Menu("Test");
      mb.add(m);

	fd = new FileDialog(this,"Visit WRL",FileDialog.LOAD);
	fd.setDirectory("."+File.separator+"parts");
	//add("North",panel);
	setMenuBar(mb);

    }

    /**********************************************************/
    /********** the class that makes the snapshot *************/
    /**********************************************************/
    public class CaptureCanvas extends Canvas3D
    {
    String strSnapshotName ;

    CaptureCanvas(java.awt.GraphicsConfiguration config) {super(config);}

    public void takeSnapshot(String filename) {
    strSnapshotName = filename;
    bTakeSnapshot = true;
    //repaint();
    postRender() ;
    }
    /********************************************************/
    public void postRender() {
    super.postRender();

    if (bTakeSnapshot) {
        bTakeSnapshot = false;
        doCapture();
                       }
                           }
    /********************************************************/

    public void doCapture()
    {
        // change le curseur
    setCursor(new Cursor(Cursor.WAIT_CURSOR));

    // definit les objets necessaires au snapshot
    try {
    ecrivain = new PrintWriter( new BufferedOutputStream(new FileOutputStream("snap.txt")));
    Dimension d = getSize();
    BufferedImage bImage = new BufferedImage(600,400 ,BufferedImage.TYPE_INT_ARGB);
    ImageComponent2D imgComp = new ImageComponent2D(ImageComponent2D.FORMAT_RGB, bImage);
    rasSnapshot = new Raster(new Point3f(), Raster.RASTER_COLOR ,0, 0, 600, 400, imgComp, null);
    ecrivain.println("before");
    // prend le snapshot
     getGraphicsContext3D().readRaster(rasSnapshot);
    ecrivain.println("after");
    }
    catch (FileNotFoundException fnfe){}
    finally {ecrivain.close();}
    // exporte le snapshot vers un fichier JPEG
       BufferedImage bi = rasSnapshot.getImage().getImage();
       FileOutputStream fOut = null;
       try {
       fOut = new FileOutputStream(strSnapshotName +".jpg");

        // definit un JPEG encoder avec qualite maximale
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(fOut);
        JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bi);
        param.setQuality(1.0f, true);
        encoder.setJPEGEncodeParam(param);

        // encode l'image
        encoder.encode(bi);
            }
        catch(ImageFormatException ife){}
        catch(IOException ioe1) {}
        finally {
            if (fOut!= null)
            { try {
               fOut.close();
               setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
               rasSnapshot = null;
                  }
             catch (IOException ioe){}
            }
        }
}
}

    /**********************************************************/
    /******end of CaptureCanvas********************************/
    /***********************************************************/
    void setupVpMenu() {
	if (vpDesc != null) {
	    MenuItem mi;
	    for (int i = 0; i < vpDesc.length; i++) {
		mi = new MenuItem(vpDesc[i]);
		mi.addActionListener(this);
		mi.setActionCommand(vpAction + i);
		vpMenu.add(mi);
	    }
	}
    }

    public static void main(String[] args)  {
   	int th, tw;
	String s;
	String urlString = null;
	if (args.length == 0) {
	    urlString = "file:" +
		System.getProperties().getProperty("user.dir") + File.separator
		+ "parts" + File.separator + "interp.wrl";
	} else {
	    if (args.length != 1) {
		System.out.println("Usage: Vrml97Player [<URL>]");
		System.exit(0);
	    } else {
		urlString = args[0];
	    }
	}

	v97p = new Vrml97Player(urlString);

	// todo get the os.name parameter, and figure out what
	// width and height borders to add to get the desired
	// canvas size.
	th = Integer.parseInt((s=System.getProperty("height"))==null?"0":s);
	tw = Integer.parseInt((s=System.getProperty("width"))==null?"0":s);
	if ( th > 0 )  h=th+H;
	if ( tw > 0 )  w=tw+W;
	v97p.setSize(w, h);
	sync = new Thread(v97p);
	sync.setPriority(Thread.NORM_PRIORITY);
	sync.start();
    }

    public void run() {
	browser=createVrmlEnv();
	browser.setAWTContainer(this);
	gotoWrl(urlString);
	show();
    }

    public void actionPerformed(ActionEvent evt) {
    CaptureCanvas vcan = v97p.new CaptureCanvas (null);

     if (evt.getSource() == snap)
     /*************************************/
       //the call to the snapshot function
    /*************************************/
      {vcan.takeSnapshot("hiba");
      }

	if(evt.getSource().equals(gotoWrl)){
	    urlString[0] = gotoWrl.getText();
	    gotoWrl(urlString);
	} else if (evt.getSource() instanceof MenuItem) {
	    String arg = evt.getActionCommand();
	    if (arg.equals("Open")) {
		String filename;
		fd.show();
		//filename = "file:"+fd.getDirectory()+File.separator+fd.getFile();
		filename = "file:"+fd.getDirectory()+fd.getFile();
		if (!filename.endsWith("null")) {
		    gotoWrl.setText(filename);
		    gotoWrl(filename);
		}
	    } else if (arg.equals("Exit")) {
		browser.shutDown();
	    } else if (arg.startsWith(vpAction)) {
		String indexString = arg.substring(vpAction.length());
		int index = Integer.valueOf(indexString).intValue();
		browser.setViewpoint(index);
	    } else if (arg.equals(resetVp)) {
		browser.resetViewpoint();
	    } else if (arg.equals("Suspend")) {
		browser.stopRender();
	    } else if (arg.equals("Resume")) {
		browser.startRender();
	    } else if (arg.equals("View/Edit Source")) {
	        f  = new ViewSourceFrame("View Source",browser);
		f.setVisible(true);
	    }
	}
    }


    Browser createVrmlEnv() {
	setLayout(new BorderLayout());
	float widthscale = 60.0f;
	int twidth;
	panel = new Panel();
	panel.setLayout(new FlowLayout(FlowLayout.LEFT));
	twidth = this.w >= 780?60:(int)(60.0 * ((float)(this.w))/780.0f);
	gotoWrl = new GotoWRLTextField(this,urlString[0],twidth);
	label = new Label("WRL:");
	panel.add(label);
	panel.add(gotoWrl);
	panel.add(snap);
	add("North",panel);
	snap.addActionListener(this);
	canvas = new Canvas3D(null);
        Browser br = new Browser(canvas);
	add("Center",canvas);
	canvas.setCursor(new Cursor(Cursor.WAIT_CURSOR));

	this.addWindowListener(wl = new WindowAdapter() {
	    public void windowIconified(WindowEvent evt) {
		browser.stopRender();
	    }
	    public void windowDeiconified(WindowEvent evt) {
		browser.startRender();
	    }
	});

	this.addComponentListener(cl = new ComponentAdapter() {
	    public void componentResized(ComponentEvent evt) {
	        gotoWrl.setColumns(Vrml97Player.w>=780?60:(int)(60.0*((float)(Vrml97Player.w))/780.0f));

	    }
	});
	return br;
    }

    void gotoWrl(String u) {
	String urls[] = new String[1];
	urls[0] = u;
	gotoWrl(urls);
    }

    synchronized void gotoWrl(String[] u) {
	try {
	    setTitle("Loading "+u[0]);
	    canvas.setCursor(new Cursor(Cursor.WAIT_CURSOR));
            browser.loadURL(u, null);
	    vpMenu.removeAll();
	    vpDesc = browser.getViewpointDescriptions();
	    setupVpMenu();
        } catch (java.io.IOException e) {
            System.err.println("IO exception reading URL");
        } catch (vrml.InvalidVRMLSyntaxException e) {
            System.err.println("VRML parse error");
	    e.printStackTrace(System.err);
	}

        setTitle(browser.getName() + " : " + browser.getDescription());
	canvas.setCursor(new Cursor(Cursor.HAND_CURSOR));
    }

    public void processEvent(AWTEvent e) {
	if(e.getID() == WindowEvent.WINDOW_CLOSING){
	    dispose();
	    System.exit(0);
	} else if (e.getID() == ComponentEvent.COMPONENT_RESIZED) {
	    gotoWrl.setColumns(this.w>=780?60:(int)(60.0*((float)(this.w))/780.0f));
	}
    }

    public void setGotoString(String s) {
	gotoWrl.setText(s);
	validate();
    }


}

