/**
 * 
 * You can add code anywhere in this file - except in the areas that are
 * written by the editor. You should not change the relative ordering of
 * the code.
 * 
 * You can remove this comment block or replace it with another.
 * 
 * @see		
 * @version	
 * @author	
 */

//this isn't quite working -- my algorithm is in GradTriangle.java 

import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.io.*;
import java.net.*;
import java.util.*;
import com.supercede.forms.*;

import Vertex2D;
import Triangle;
import ppmDecoder;

public class Form1 extends SuperCedeApplet implements Serializable
{
	static int CHUNKSIZE = 100;
    Raster reference, raster;
    Drawable triList[];
    int triangles;
    Color background;
    Image screen;
    int state;
	Triangle tri[];
	
	//Raster reference, raster;
	//Image screen;

	void form1PreInit()
	{
		// You can add code anywhere in this method.
		// This method is called PRIOR to form initialization.
		// NOTE: The form has NOT been initialized yet. Do not modify the form itself in this method.
	}

	void form1PostInit()
	{
		// You can add code anywhere in this method.
		// This method is called AFTER form initialization.
	}

	public void init()
	{
		// You can add code anywhere in this method.
		resize(400, 400);
		// Read in the reference image
		ppmDecoder ppmDecoder = new ppmDecoder();
        screen = ppmDecoder.getImage(getCodeBase(), "hexcone.ppm");
        
        reference = new Raster(screen);
        // Create a raster for rendering
        background = Color.white;
        raster = new Raster(reference.getWidth(), reference.getHeight());

        // Read in the triangle file
        triList = new Triangle[CHUNKSIZE];
        triangles = 0;
        InputStream is = null;
        try {
            is = new URL(getDocumentBase(), getParameter("http://web.mit.edu/ianross/6.837/hexcone.tri")).openStream();
            ReadInput(is);
            is.close();
        } catch (IOException e) {
            showStatus("Error reading "+getParameter("http://web.mit.edu/ianross/6.837/hexcone.tri"));
        }
        state = 0;
    
		SuperCedeInit();   // Do not remove this line.
	}
	
	// parse a floting point number
    private float getNumber(StreamTokenizer st) throws IOException {
        st.nextToken();
        return (Float.valueOf(st.sval).floatValue());
    }
    
    // parse a packed integer in hex, octal, or decimal
    private int getColor(StreamTokenizer st) throws IOException {
        st.nextToken();
        int pix;
        if (st.sval.startsWith("0x") || st.sval.startsWith("0X")) {
                pix = (int) Long.parseLong(st.sval.substring(2), 16);
            } else
            if (st.sval.startsWith("0") || st.sval.length() > 1) {
                pix = (int) Long.parseLong(st.sval.substring(1), 8);
            } else
                pix = Integer.parseInt(st.sval);
        return pix;
    }

	// extend the triangle array if needed
    private void growList() {
        Drawable newList[] = new Drawable[triList.length+CHUNKSIZE];
        System.arraycopy(triList, 0, newList, 0, triList.length);
        triList = newList;
        CHUNKSIZE = (3*CHUNKSIZE)/2;
    }
    
    // define legal characters for our parser
    // The remainder of a line after a '#' is ignored
    // you might find this helpful for debugging
    private void configureParser(StreamTokenizer st) {
            st.ordinaryChars(0, 255);
            st.wordChars('a', 'f');
            st.wordChars('A', 'F');
            st.wordChars('0', '9');
            st.wordChars('-', '-');
            st.wordChars('.', '.');
            st.wordChars('x', 'x');
            st.wordChars('X', 'X');
            st.whitespaceChars(' ', ' ');
            st.whitespaceChars('\t', '\t');
            st.whitespaceChars('\n', '\n');
            st.whitespaceChars('\r', '\r');
        st.eolIsSignificant(false);
        st.commentChar('#');
    }

 	// Scan the triangle file
    public void ReadInput(InputStream is) throws IOException {
        Vertex2D v1, v2, v3;
        int currentvert = 0;
        float x, y;
        int pix;
        
            StreamTokenizer st = new StreamTokenizer(is);
            configureParser(st);
        while (st.nextToken() != StreamTokenizer.TT_EOF) {
            st.pushBack();
            x = getNumber(st);
            y = getNumber(st);
            pix = getColor(st);
            v1 = new Vertex2D(x, y, pix);
            x = getNumber(st);
            y = getNumber(st);
            pix = getColor(st);
            v2 = new Vertex2D(x, y, pix);
            x = getNumber(st);
            y = getNumber(st);
            pix = getColor(st);
            v3 = new Vertex2D(x, y, pix);
            if (triangles == triList.length) growList();
            triList[++triangles] = new Triangle(v1, v2, v3);	//modified
        //    System.out.println("A"+triangles);
         }
    }
    
    String message[] = { "Reference", "Rendered", "Difference" };

	public void start()
	{
		// You can add code anywhere in this method.

		SuperCedeStart();   // Do not remove this line.
	}

	public void stop()
	{
		// You can add code anywhere in this method.

		SuperCedeStop();   // Do not remove this line.
	}
	
	public void paint(Graphics g)
	{
		g.drawString("Created with Microsoft Visual J++ Version 1.1", 10, 20);
		
		g.drawImage(screen, 0, 0, this);
    	g.setColor(Color.black);
    	g.drawString(message[state], 10, 20);
    	if (state == 2) {
    	    double t = (badpixels*100.0)/pixels;
    	    g.drawString("Bad pixels = "+t+"%", 10, 36);
    	    if (badpixels > 0)
    	        t = ((double)pixelerror)/badpixels;
    	    else
    	        t = 0;
    	    g.drawString("Ave error  = "+t, 10, 52);
       	 g.drawString("Time  = "+time+" ms", 10, 68);
    	}
	}

	public void update(Graphics g) {
        paint(g);
	}

	long time;
	int pixels;
	int badpixels;
	int pixelerror;

	public boolean mouseDown(Event e, int x, int y) {
		if (state == 0) {
	        raster.fill(background);
	        time = System.currentTimeMillis();
   	     //System.out.println("B"+triangles);
   	     for (int i = 0; i < triangles; i++)
   	          triList[i].Draw(raster);				//call draw here
        time = System.currentTimeMillis() - time;
        screen = raster.toImage( );
    } else
    if (state == 1) {
        int pixa, pixb, t;
        pixels = raster.pixel.length;
        badpixels = 0;
        pixelerror = 0;
        for (int i = 0; i < pixels; i++) {
            pixa = raster.pixel[i];
            pixb = reference.pixel[i];
            if (pixa != pixb) {
	            badpixels += 1;
                t = Math.abs((pixa & 255) - (pixb & 255));
                t += Math.abs(((pixa >> 8) & 255) - ((pixb >> 8) & 255));
                t += Math.abs(((pixa >> 16) & 255) - ((pixb >> 16) & 255));
                pixelerror += t;
                int b = (255 - t);
                if (b < 0) b = 0;
                int g = (t > 382) ? (637 - t) : (t - 127);
                if (g < 0) g = 0;
                int r = (t - 510);
                if (r < 0) r = 0;
                raster.pixel[i] = ((((0xff00 + r) << 8) + g) << 8) + b;
            } else {
                raster.pixel[i] = 0xffffffff;
            }
        }
        screen = raster.toImage( );
    } else
    if (state == 2) {
        screen = reference.toImage( );
    }
    state = (state + 1) % 3;
    repaint();
    return true;
}

	// SuperCede Begin 2.0 Form Members
	// Do not remove the Begin and End markers.
	// The editor will rewrite the contents of this section each time the form is saved.

	private void SuperCedeConstructor() throws IOException, ClassNotFoundException, ClassCastException, SuperCedeInvalidStateException
	{
		// Construct the actual connectors to give to our base class.

		Vector connectors = null;
		super.initializeThis(connectors);
	}

	public Form1() throws IOException, ClassNotFoundException, ClassCastException, SuperCedeInvalidStateException
	{
		super();

		form1PreInit();
		SuperCedeConstructor();
		form1PostInit();
	}

	private void SuperCedeInit()
	{
	}

	private void SuperCedeStart()
	{
	}

	private void SuperCedeStop()
	{
	}

	// SuperCede End 2.0 Form Members
}

// SuperCede Begin 2.0 Form Connectors
// Do not remove the Begin and End markers.
// The editor will rewrite the contents of this section each time the form is saved.

// The following line must be the last line in the file.
// SuperCede End 2.0 Form Connectors
