//******************************************************************************
// threed.java:	Applet
//
//******************************************************************************
import java.applet.*;
import java.awt.*;
import java.awt.image.MemoryImageSource;
import java.awt.image.ColorModel;
import java.io.*;

import defines;
import linetype;
import view;
import globals;


//==============================================================================
// Main Class for applet threed
//
//==============================================================================
public class threed extends Applet implements Runnable
{
	// THREAD SUPPORT:
	//		m_threed	is the Thread object for the applet
	//--------------------------------------------------------------------------
	Thread	 m_threed = null;


	// PARAMETER NAMES
	//--------------------------------------------------------------------------

	String m_filename = "http://entropy.uark.edu/~lhollowa/threed/test.dxf";

	final String PARAM_filename = "filename";
	
	
	
	
	// ANIMATION SUPPORT:
	//		m_Graphics		used for storing the applet's Graphics context
	//		m_Images[]		the array of Image objects for the animation
	//		m_nCurrImage	the index of the next image to be displayed
	//		m_ImgWidth		width of each image
	//		m_ImgHeight		height of each image
	//		m_fAllLoaded	indicates whether all images have been loaded
	//		NUM_IMAGES 		number of images used in the animation
	//--------------------------------------------------------------------------
	
	
	
	
	
	private Graphics m_Graphics;
	private Image	 m_Images[];
	private int 	 m_nCurrImage;
	private int 	 m_nImgWidth  = 0;
	private int 	 m_nImgHeight = 0;
	private boolean  m_fAllLoaded = false;
	private final int NUM_IMAGES = 18;
	
	private int val;
	private double di;


	private globals glob = new globals();
	private defines def = new defines();

	private int[] VidBuf = new int[(int)(def.WIDTH * def.HEIGHT)];
	private PolyObj World = new PolyObj();

	private IOException error;

	private matrix3d M;// = new matrix3d();
	private View V = new View();
	private int step = 5;

	private boolean good;

	private Color background = new Color(0,0,255);

	private int framecount = 0;




	// threed Class Constructor
	//--------------------------------------------------------------------------
	public threed()
	{
		// TODO: Add constructor code here
//		m_Graphics = getGraphics();
//		World = new PolyObj(m_Graphics);
		for(int i=0;i<(int)(def.WIDTH * def.HEIGHT);i++)
			VidBuf[i]=0;

//		World.LoadDXF("file:///D|/MSDEV/test/threed/Test.DXF",VidBuf);
//		World.LoadDXF("file:///C|/Lance/threed/Test.dxf",VidBuf);
//		World.LoadDXF("file:///C|/Lance/threed/Test3.dxf",VidBuf);
//		World.LoadDXF("http://entropy.uark.edu/~lhollowa/threed/test.dxf",VidBuf);
//		World.WriteBIN("file:///D|/MSDEV/test/threed/Test2.BIN");
 //    	m_Graphics = getGraphics();



//		World.ReadBIN("D:\\MSDEV\\test\\threed\\Test.bin",VidBuf);
//		di=World.ReadBIN("file:///D|/MSDEV/test/threed/Test.bin",VidBuf);
//		World.ReadBIN("http://entropy.uark.edu/~lhollowa/threed/test.bin",VidBuf);
//		World.ReadBIN("test.bin",VidBuf);
//		RunWorld();


/*		M = new matrix3d();
//		background = Color.blue;

		InitZBuffer();
		M.Initialize();
		M.Translate(-50, 100, 150);
		M.Rotate(280,0,0);
		ClearBuffer();
				
		World.Display(M,VidBuf);
 */
	}

	// APPLET INFO SUPPORT:
	//		The getAppletInfo() method returns a string describing the applet's
	// author, copyright date, or miscellaneous information.
    //--------------------------------------------------------------------------
	public String getAppletInfo()
	{
		return "Name: threed\r\n" +
		       "Author: Lance Holloway\r\n" +
			   "Weremoose Productions\r\n" +
		       "Created with Microsoft Visual J++ Version 1.0";
	}



	// Sets up the parameters
	public String[][] getParameterInfo()
	{
		String[][] info=
		{
			{PARAM_filename, "String", "URL for DXF file"}
		};
		return info;
	}// getParameterInfo()



	// The init() method is called by the AWT when an applet is first loaded or
	// reloaded.  Override this method to perform whatever initialization your
	// applet needs, such as initializing data structures, loading images or
	// fonts, creating frame windows, setting the layout manager, or adding UI
	// components.
    //--------------------------------------------------------------------------
	public void init()
	{

		String param;

		param = getParameter(PARAM_filename);
		if(param != null)
			m_filename = param;

		good = World.LoadDXF(m_filename);

        // If you use a ResourceWizard-generated "control creator" class to
        // arrange controls in your applet, you may want to call its
        // CreateControls() method from within this method. Remove the following
        // call to resize() before adding the call to CreateControls();
        // CreateControls() does its own resizing.
        //----------------------------------------------------------------------
		resize((int)def.WIDTH, (int)def.HEIGHT);

		if(good)
		{
			val = 0;

			M = new matrix3d();

			InitZBuffer();
			M.Initialize();
			M.Translate(-50, 100, 150);
			M.Rotate(280,0,0);
			ClearBuffer();
				
			World.Display(M,VidBuf);

		}

		// TODO: Place additional initialization code here
	}

	// Place additional applet clean up code here.  destroy() is called when
	// when you applet is terminating and being unloaded.
	//-------------------------------------------------------------------------
	public void destroy()
	{
		// TODO: Place applet cleanup code here
	}

    // ANIMATION SUPPORT:
    //-------------------------------------------------------------------------
	// threed Paint Handler
	//--------------------------------------------------------------------------
	public void paint(Graphics g)
	{
		// ANIMATION SUPPORT:
		//		The following code displays a status message until all the
		// images are loaded. Then it calls displayImage to display the current
		// image.
		//----------------------------------------------------------------------
/*		if (m_fAllLoaded)
		{
			Rectangle r = g.getClipRect();
			
			g.clearRect(r.x, r.y, r.width, r.height);
			displayImage(g);
		}
		else
			g.drawString("Loading images...", 10, 20);
  */
		// TODO: Place additional applet Paint code here
		  	
//			World.Display(M,VidBuf);

		if(good)
		{
			Image img = createImage(new MemoryImageSource((int)def.WIDTH, (int)def.HEIGHT, ColorModel.getRGBdefault(),VidBuf, 0, (int)def.WIDTH));
			m_Graphics.drawImage(img, 0, 0, Color.black, null);	
		}
		else
		{
			m_Graphics.drawString("File Not Found!", 100, 70);
		}


	//	VidBuf[20] = 255;

	//	Image img = createImage(new MemoryImageSource((int)def.WIDTH, (int)def.HEIGHT, VidBuf, 0, (int)def.WIDTH));
	//	g.drawImage(img, 0, 0, null);

	}

	//		The start() method is called when the page containing the applet
	// first appears on the screen. The AppletWizard's initial implementation
	// of this method starts execution of the applet's thread.
	//--------------------------------------------------------------------------
	public void start()
	{
		if (m_threed == null)
		{
			m_threed = new Thread(this);
			m_threed.start();
		}
		// TODO: Place additional applet start code here
	}
	
	//		The stop() method is called when the page containing the applet is
	// no longer on the screen. The AppletWizard's initial implementation of
	// this method stops execution of the applet's thread.
	//--------------------------------------------------------------------------
	public void stop()
	{
		if (m_threed != null)
		{
			m_threed.stop();
			m_threed = null;
		}

		// TODO: Place additional applet stop code here
	}



	public boolean keyDown(Event evt, int nKey)
	{
		// Key pressed

		if(good)
		{
		Image img;
		switch(evt.key)
		{
			case Event.UP:
				if(evt.modifiers == Event.SHIFT_MASK)
					M.Rotate(-step,0,0);
				else
					M.Translate(0,0,-step);
				World.Display(M,VidBuf);
				img = createImage(new MemoryImageSource((int)def.WIDTH, (int)def.HEIGHT, ColorModel.getRGBdefault(),VidBuf, 0, (int)def.WIDTH));
				m_Graphics.drawImage(img, 0, 0, Color.black, null);	
				break;
			case Event.DOWN:
				if(evt.modifiers == Event.SHIFT_MASK)
					M.Rotate(step,0,0);
				else
					M.Translate(0,0,step);
				World.Display(M,VidBuf);
				img = createImage(new MemoryImageSource((int)def.WIDTH, (int)def.HEIGHT, ColorModel.getRGBdefault(),VidBuf, 0, (int)def.WIDTH));
				m_Graphics.drawImage(img, 0, 0, Color.black, null);	
				break;
			case Event.RIGHT:
				if(evt.modifiers == Event.SHIFT_MASK)
					M.Rotate(0,0,step);
				else
					M.Rotate(0,-step,0);
				World.Display(M,VidBuf);
				img = createImage(new MemoryImageSource((int)def.WIDTH, (int)def.HEIGHT, ColorModel.getRGBdefault(),VidBuf, 0, (int)def.WIDTH));
				m_Graphics.drawImage(img, 0, 0, Color.black, null);	
				break;
			case Event.LEFT:
				if(evt.modifiers == Event.SHIFT_MASK)
					M.Rotate(0,0,-step);
				else
					M.Rotate(0,step,0);
				World.Display(M,VidBuf);
				img = createImage(new MemoryImageSource((int)def.WIDTH, (int)def.HEIGHT, ColorModel.getRGBdefault(),VidBuf, 0, (int)def.WIDTH));
				m_Graphics.drawImage(img, 0, 0, Color.black, null);	
				break;

		}
//		repaint();
		framecount++;
		if(framecount > 10)
		{
			ClearBuffer();
			glob.ZTrans = 0;
			System.gc();
		}
		else
			glob.ZTrans += (1 << glob.ZSTEP_PREC);
		V.clear();
		}
		return true;
	}


	// THREAD SUPPORT
	//		The run() method is called when the applet's thread is started. If
	// your applet performs any ongoing activities without waiting for user
	// input, the code for implementing that behavior typically goes here. For
	// example, for an applet that performs animation, the run() method controls
	// the display of images.
	//--------------------------------------------------------------------------
	public void run()
	{
//		matrix3d M = new matrix3d();
//		View V = new View();
		long QuitFlag = 0, StartTime, EndTime, FrameCount=0, MaxWait;
		
//		InitZBuffer();
    	m_Graphics = getGraphics();

/*		if(!good)
		{
			m_Graphics.drawString("File Not Found!", 100, 70);
		}
  */
//		while(true)
//		{
			try
			{
/*				M.Initialize();
			//	M.Translate(0, -600, 0);
			//	M.Translate(0, 100, 2000);
				M.Translate(0, -300, 500);
			//	M.Rotate(20,0,0);
				ClearBuffer();
				
				val=1;
				World.Display(M,VidBuf);
				val=2;
				int step = 5;

				for(int i=1;i<2100;i+=step)
				{
				//	M.Translate(0,0,-step);
					M.Rotate(0,step,0);
					World.Display(M,VidBuf);
					ClearBuffer();
					V.clear();
*/		  

				//This goes in a while loop eventually
			/*	M.Translate(0,0,-V.ZPos);
				M.Rotate(-V.XRot, -V.YRot, -V.ZRot);
				V.clear();
			  */



				//MaxWait = (long) pow(2,31-ZSTEP_PREC);
				//repaint();
/*				Image img = createImage(new MemoryImageSource((int)def.WIDTH, (int)def.HEIGHT, ColorModel.getRGBdefault(),VidBuf, 0, (int)def.WIDTH));
				
				m_Graphics.drawImage(img, 0, 0, Color.black, null);
				for(int k=0;k<5;k++)
				{
					m_Graphics.drawString(String.valueOf(VidBuf[k*3]), 10,k*15+10);
					m_Graphics.drawString(String.valueOf(VidBuf[k*3+1]), 50,k*15+10);
					m_Graphics.drawString(String.valueOf(VidBuf[k*3+2]), 90,k*15+10);
				}
				}
				m_Graphics.drawString(String.valueOf(VidBuf[101]), 10,70);
				m_Graphics.drawString(String.valueOf(VidBuf[100]), 10,80);
				m_Graphics.drawString(String.valueOf(VidBuf[10000]), 10, 150);
				m_Graphics.drawString(m_Graphics.toString(), 10, 130);
				m_Graphics.drawString(String.valueOf(VidBuf[10001]), 10, 180);
*/			}
			catch (InterruptedException e)
			{
				m_Graphics.drawString("Interrupted", 100,10);
				stop();
			}
			catch (Exception e)
			{
				m_Graphics.drawString(e.toString(), 10,100);
				Integer Val = new Integer(val);
				m_Graphics.drawString(Val.toString(), 10, 150);
				m_Graphics.drawString(String.valueOf(VidBuf[10000]),10,170);
				m_Graphics.drawString(String.valueOf(VidBuf[10001]),50,170);
				m_Graphics.drawString(String.valueOf(VidBuf[10002]),80,170);
				stop();
			}
		//	stop();
//		}
	}



	//-------------------------------------------------------

	public void InitZBuffer()
	{
		// Allocate memory for Z-buffer
		glob.ZBuffer = new long[(int)(def.WIDTH * def.HEIGHT)];
	}// InitZBuffer()

	//--------------------------------------------------------

	public void ClearBuffer()
	{
		// Clear the Z-buffer
		
		for(int Index = 0; Index < (int)(def.WIDTH * def.HEIGHT); Index++)
		{
			glob.ZBuffer[Index]=0;
		}

	}// ClearBuffer()


	// TODO: Place additional applet code here

}

