package vgp.tutor.loader;

import java.applet.Applet;
import java.awt.*;
import java.io.BufferedReader;
import java.io.IOException;

import jv.geom.PgPointSet;
import jv.geom.PgPolygon;
import jv.geom.PgElementSet;
import jv.object.*;
import jv.project.PgGeometryIf;
import jv.project.PvGeometryIf;
import jv.project.PvDisplayIf;
import jv.project.PgJvxSrc;
import jv.viewer.PvViewer;

/**
 * Tutorial on geometry loaders. This tutorial explains how to write
 * and use an own geometry loader within JavaView.
 * <p>
 * The loader used in the init() method of this applet can be replaced with
 * any of the built-in loaders (jv.loader.*, jvx.loader.*) of JavaView.
 * 
 * @see			vgp.tutor.model.PaModel
 * @author		Konrad Polthier
 * @version		22.02.03, 1.15 revised (kp) Check for unknown geometry types.<br>
 *					06.10.02, 1.10 revised (kp) Use codebase when loading a file.<br>
 *					09.11.01, 1.00 created (kp)
 */
public class PaLoader extends Applet {
	/** frame if run standalone, null if run as applet. */
	public		Frame				m_frame			= null;
	/** 3D-viewer window for graphics output and which is embedded into the applet. */
	protected	PvViewer			m_viewer;

	/** Interface of applet to inform about author, version, and copyright. */
	public String getAppletInfo() {
		return "Name: "		+ this.getClass().getName()+ "\r\n" +
				 "Author: "		+ "Konrad Polthier" + "\r\n" +
				 "Version: "	+ "1.15" + "\r\n" +
				 "Tutorial on usage of parsing an own geometry file format." + "\r\n";
	}

	/**
	 * Configure and initialize the viewer, load system and user projects.
	 * One of the user projects must be selected here.
	 * <p>p
	 * Note, for tutorial reasons this method still continues
	 * even if parsing errors appear.
	 */
	public void init() {
		// Create viewer for viewing 3d geometries
		m_viewer = new PvViewer(this, m_frame);
		PvDisplayIf disp = m_viewer.getDisplay();

		// Get the name of the geometry file either as applet parameter
		// or, if running as application, as command line argument.
		String fileName = m_viewer.getParameter("filename");
		String ext = PsUtil.getFileExtension(fileName);
		if (ext == null) {
			if (PsDebug.WARNING) PsDebug.warning("missing extension in file="+fileName);
		}

		// The geometries will be generate in the parser. This parser
		// returns exactly one geometry.
		PgJvxSrc [] geomArr = null;
		
		// Open the file resp. URL. Getting the codeBase from PsConfig
		// avoids a distinction between applets and applications.
		BufferedReader in = PsUtil.open(PsConfig.getCodeBase()+fileName);
		if (in == null) {
			if (PsDebug.WARNING) PsDebug.warning("could not open file = "+fileName);
		} else {
			// Parse the file
			PgAbcLoader loader	= new PgAbcLoader();
			String index			= m_viewer.getParameter("vgp.tutor.loader.indexfirstvertex");
			if (index != null) {
				int ind = Integer.parseInt(index);
				loader.setFirstVertexIndex(ind);
			}
			geomArr = loader.read(in);

			// Before we continue, first close the file.
			try { in.close(); } catch (IOException ex) {}
		}
		
		if (geomArr==null || geomArr[0]==null) {
			if (PsDebug.WARNING) PsDebug.warning("error when reading file = "+fileName);
		} else {
			for (int i=0; i<geomArr.length; i++) {
				// Assign geometry a name based on the file name.
				if (fileName != null) {
					String baseName = PsUtil.getFileBaseName(fileName);
					if (geomArr.length == 1)
						geomArr[i].setName(baseName);
					else
						geomArr[i].setName(baseName+"["+String.valueOf(i)+"]");
				}
				// Optionally, convert PgJvxSrc into an element set or point set
				// since PgJvxSrc does not have an info or material panel.
				// 
				// For efficiency, the jv.geom.* data structures may be directly
				// used within the loader. In JavaView, the loaders avoid using
				// classes from jv.geom to allow jvLite not to depend on jv.geom.
				PgGeometryIf geom = null;
				switch (geomArr[i].getType()) {
				case PvGeometryIf.GEOM_POINT_SET:
					geom = new PgPointSet(geomArr[i].getDimOfVertices());
					break;
				case PvGeometryIf.GEOM_POLYGON:
					geom = new PgPolygon(geomArr[i].getDimOfVertices());
					break;
				case PvGeometryIf.GEOM_POLYGON_SET:
					geom = new PgPolygon(geomArr[i].getDimOfVertices());
					break;
				case PvGeometryIf.GEOM_ELEMENT_SET:
					geom = new PgElementSet(geomArr[i].getDimOfVertices());
					break;
				default:
					PsDebug.warning("geometry["+i+"] has unknown type = "+geomArr[i].getType());
				}
				// If geometry does not have a recognized type, for example,
				// if this loader parses a geometry file produced with some future
				// version of JavaView, then we constrain to using the PgJvxSrc.
				if (geom == null)
					geom = geomArr[i];
				else
					geom.setJvx(geomArr[i]);
				
				// Add geometry to the display.
				disp.addGeometry(geom);
				if (i == 0)
					disp.selectGeometry(geom);
			}
		}
		
		// Get 3d display from viewer and add it to applet
		setLayout(new BorderLayout());
		add((Component)m_viewer.getDisplay(), BorderLayout.CENTER);
		validate();
	}
	/**
	 * Standalone application support. The main() method acts as the applet's
	 * entry point when it is run as a standalone application. It is ignored
	 * if the applet is run from within an HTML page.
	 */
	public static void main(String args[]) {
		PaLoader va	= new PaLoader();
		// Create toplevel window of application containing the applet
		Frame frame	= new jv.object.PsMainFrame(va, args);
		frame.pack();
		frame.setBounds(new Rectangle(420, 5, 640, 550));
		frame.setVisible(true);
		va.m_frame = frame;
		va.init();
		va.start();
	}
	
	/** Print info while initializing applet and viewer. */
	public void paint(Graphics g) {
		g.setColor(Color.blue);
		g.drawString("Geometry Browser, Version "+PsConfig.getVersion(), 20, 40);
		g.drawString("Loading Projects .....", 20, 60);
	}

	/**
	 * Does clean-up when applet is destroyed by the browser.
	 * Here we just close and dispose all our control windows.
	 */
	public void destroy()	{ m_viewer.destroy(); }

	/** Start viewer, e.g. start animation if requested */
	public void start()		{ m_viewer.start(); }

	/** Stop viewer, e.g. stop animation if requested */
	public void stop()		{ m_viewer.stop(); }
}
