// The application class for C4 Hypercube program.
// Dan Talayco
// March 1998
//
// This is the class which handles the buttons and
// rotation commands for the cube.  Both visual and
// face rotations are button driven.
//
// NEW PROBLEM:  We have to find a different way to project
// the 4 d matrix to 3 dimensions.  Or rethink what this means.
// The orientation matrix (as a 4 d matrix) is an orthonormal
// matrix.  The 3d projection is not.  It needs to be if our cube
// faces are to look like cubes.  The question is, what does it mean
// to project an arbitrary 4 d matrix to 3 dimensions.  Should we
// normalize the resulting 3d matrices?

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.util.EventListener;

public class CubeApplet extends Applet 
    implements  ActionListener { //, ItemListener  {
//, , MouseMotionListener
//{


    C4VCube C;
//    Image OffScrImg;
//    Graphics OffScrG;
    int hsize,vsize;  // of an axis panel
//    int cx, cy; // center coords
    
//    int divX, divY;  // for converting drag coords to rotation amount.
    
    int myHsize, myVsize;
    
    boolean DEBUG = true;

//	Choice WhichFace; // for visual rotation
	Button VResetButton;
    Button ResetButton;
	Button ShowButton;
	Button AllXTurn;
	Button AllYTurn;
//	Choice
	Button QuitButton;
    
    int VRotFace;  /// Holds the code 0 to 7 of which face should be rotated
    
    Button initButton(String S, Panel P) {	
    	Button B = new Button (S);
    	P.add(B);
    	B.addActionListener(this);
    	return B;
    	
    }
    
    public void init() {
    	int i, j, index;
//    	setBackground(Color.black);
  //  	setLocation(0,0);
    	myHsize = getSize().width;
    	myVsize = getSize().height;
    	
/*    	cx = myHsize/2;
    	cy = myVsize/2;
    	
    	divX = myHsize/20;
    	divY = myVsize/20;
*/    	
    	hsize = 150;
    	vsize = 200;
	   	// Here's the cube:
    	C = new C4VCube(0,0,hsize,vsize);
		
		setLayout(new BorderLayout());
		
		Panel Center = new Panel();
		Center.setSize(4*hsize,2*vsize);
		GridLayout GL = new GridLayout(2,4);
		GL.setHgap(5); GL.setVgap(0);
		Center.setLayout(GL);
		for (i = 0; i<8; i++)
			Center.add(C.FacePanel(i));
		add(Center,"Center");
		
		Panel P = new Panel();
		ResetButton = initButton("Reset Cube",P);
 		ShowButton = initButton("Info",P);
 		QuitButton = initButton("Quit",P);
 		VResetButton = initButton("Visual Reset",P);
		AllXTurn = initButton("V Rotate All x",P);
		AllYTurn = initButton("V Rotate All y",P);

//        addMouseMotionListener(this);

//		P.add(new Label("     Dragging affects face:  "));
		
/*		WhichFace = new Choice();
		index = 0;
		for (j=1; j>-2; j-=2) 
			for (i=0; i<4; i++) 
				WhichFace.addItem("Axis " + i + "Face " + j + ": " + index++);
		WhichFace.addItemListener(this);
		
		P.add(WhichFace);
*/		
		
		add(P, "North");
		
		if (DEBUG) TestFCFunction();
    }  // end of init function.
    
    // Double buffering
/*    public void update(Graphics gc) {
    	if (OffScrImg == null) {
    		OffScrImg = createImage(getSize().width, getSize().height);
    		OffScrG = OffScrImg.getGraphics();
    		}
    	paint(OffScrG);
    	gc.drawImage(OffScrImg, 0, 0, this);
    	}

    public void paint( Graphics gc ) {
//        gc.setColor(Color.white);
  //      gc.fillRect(0,0,getSize().width, getSize().height);
//        C.RenderCube(gc);
    }
*/    
/*    // A drag event triggers a visual rotation
    public void mouseDragged( MouseEvent e ) {
    	int x = e.getX(), y = e.getY();
    	
    	if(DEBUG) System.out.println("Dragging");

    	C.VRotate(VRotFace, (cx-x)/divX, (y-cy)/divY);
    } // mouse drag

    public void mouseMoved( MouseEvent e ) { }
*/


    public void actionPerformed( ActionEvent e ) {
    	int i, j;
        if (e.getSource() == ResetButton) {
        	C.ResetCube();
        	C.RenderCube();
        	return;
        	}
		if (e.getSource() == AllXTurn) {
			C.VRotate(true,25);
			C.RenderCube();
			return;
			}
		if (e.getSource() == AllYTurn) {
			C.VRotate(false,25);
			C.RenderCube();
			return;
			}
		if (e.getSource() == ResetButton) {
        	C.ResetCube();
        	C.RenderCube();
        	return;
        	}

        if (e.getSource() == VResetButton)  {
        	C.VReset();
        	C.RenderCube();
        	}

        if (e.getSource() == ShowButton) 
        	C.ShowInfo();

		if (e.getSource() == QuitButton)
			{
				C.quit();
				destroy();
			}
//		C.repaint();
//        repaint();
//        if (C.DEBUG) System.out.println(C.toString());
    }


/*	public void itemStateChanged(ItemEvent e) {
		int i; String which = (e.getItem()).toString();
		for (i=0; i<8; i++)
			if (which.endsWith(String.valueOf(i))) {
				VRotFace = i;
				return;
				}
		}
*/

	// test the indexing function for Face coordinates
    void TestFCFunction() {
    	int face,i,j,k;
    	System.out.println("Testing FCtoIn Function.");
    	for ( face=0; face<8; face++)
			for ( i=1; i>-2; i--)
	    		for ( j=1;j>-2;j--)
	    			for ( k=1; k>-2; k--)
			    		System.out.println("From " + face + " " + i + " " + j + " " + k +
	    				" to " + C.FCtoIn(face, i, j, k));
    	System.out.println("Testing FCtoCorIn Function.");
    	for ( face=0; face<8; face++)
			for ( i=1; i>-2; i-=2)
	    		for ( j=1;j>-2;j-=2)
	    			for ( k=1; k>-2; k-=2)
			    		System.out.println("From " + face + " " + i + " " + j + " " + k +
	    				" to " + C.FCtoCorIn(face,i, j, k));
	}
	

}  // end of class cube applet
