import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import java.util.*;

import javax.media.j3d.*;
import javax.vecmath.*;

/**
Solution to Lab 8 by Rod Harris
*/

public class Lab8a
{
	private MyVirtualUniverse vu = new MyVirtualUniverse();

	private JTextArea t3dTextArea = new JTextArea();

	private NumberFormat formatter = NumberFormat.getInstance();

	private Matrix4d t3dVals = new Matrix4d();

	private Random rnd = new Random();

	private double dv = 1;

	private double vel = 0;

	private double da = 0.1;

	private Transform3D rotateT3D = new Transform3D();

	private Transform3D viewT3D = new Transform3D();

	public static void main(String[] args)
	{
		new Lab8a();
	}


	public Lab8a()
	{
		ApplicationFrame appFrame = new ApplicationFrame("Lab 8 - Plane Movement Metaphor", 800, 600);
		appFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		JPanel mainPanel	= new JPanel(new BorderLayout());
		JPanel southPanel	= new JPanel(new BorderLayout());
		JPanel t3dPanel		= new JPanel();
		JPanel buttonPanel	= new JPanel(new GridLayout(3,3));

		mainPanel.add(vu.getBoard(), BorderLayout.CENTER);
		mainPanel.add(southPanel, BorderLayout.SOUTH);
		southPanel.add(t3dPanel, (BorderLayout.WEST));
		southPanel.add(buttonPanel, (BorderLayout.CENTER));

		buttonPanel.add(new JButton(new ButtonAction("Dec Vel")));
		buttonPanel.add(new JButton(new ButtonAction("Move")));
		buttonPanel.add(new JButton(new ButtonAction("Inc Vel")));
		buttonPanel.add(new JButton(new ButtonAction("Roll Left")));
		buttonPanel.add(new JButton(new ButtonAction("Pitch Up")));
		buttonPanel.add(new JButton(new ButtonAction("Roll Right")));
		buttonPanel.add(new JButton(new ButtonAction("Yaw Left")));
		buttonPanel.add(new JButton(new ButtonAction("Pitch Down")));
		buttonPanel.add(new JButton(new ButtonAction("Yaw Right")));

		t3dPanel.add(t3dTextArea);

		formatter.setMaximumFractionDigits(2);
		formatter.setMinimumIntegerDigits(1);
		formatter.setMinimumFractionDigits(2);

		setTextArea();

		appFrame.getContentPane().add(mainPanel);

		addContent();

		appFrame.setVisible(true);
	}


	public void addContent()
	{
		for (int x=-100; x<=100; x+=5)
		{
			for (int z=-100; z<=100; z+=5)
			{
				if (rnd.nextInt(100) <= 20)
				{
					addTree(x, z, 4, 1);
				}
			}
		}
	}


	public void addTree(double x, double z, double height, double radius)
	{
		BranchGroup bg = new BranchGroup();

		TransformGroup tg = new TransformGroup();

		Transform3D t3d = new Transform3D();

		t3d.set(new Vector3d(x, -5, z));

		tg.setTransform(t3d);

		tg.addChild(new Tree(height, radius));

		bg.addChild(tg);

		vu.addBranchGraph(bg);
	}


	private void setTextArea()
	{
		viewT3D.get(t3dVals);

		String s = "\n";
		for(int r=0; r<4; r++)
		{
			s += "  ";
			for (int c=0; c<4; c++)
			{
				double d = t3dVals.getElement(r, c);

				if (!(d<0))
				{
					s+= " ";
				}

				s+= formatter.format(d);
				if (c<3)
				{
					s += " , ";
				}
			}
			s += "    \n";
		}

		t3dTextArea.setText(s);
	}


	private void buttonPressed(String name)
	{
		if (name.equals("Dec Vel"))
		{
			vel -= dv;
			if (vel<0)
			{
				vel = 0;
			}
		}
		else if (name.equals("Pitch Up"))
		{
			rotateT3D.rotX(da);
			viewT3D.mul(rotateT3D);
			vu.getViewTG().setTransform(viewT3D);
		}
		else if (name.equals("Inc Vel"))
		{
			vel += dv;
			if (vel>5)
			{
				vel = 5;
			}
		}
		else if (name.equals("Roll Left"))
		{
			rotateT3D.rotZ(da);
			viewT3D.mul(rotateT3D);
			vu.getViewTG().setTransform(viewT3D);
		}
		else if (name.equals("Move"))
		{
			move(-vel);
		}
		else if (name.equals("Roll Right"))
		{
			rotateT3D.rotZ(-da);
			viewT3D.mul(rotateT3D);
			vu.getViewTG().setTransform(viewT3D);
		}
		else if (name.equals("Yaw Left"))
		{
			rotateT3D.rotY(da);
			viewT3D.mul(rotateT3D);
			vu.getViewTG().setTransform(viewT3D);
		}
		else if (name.equals("Pitch Down"))
		{
			rotateT3D.rotX(-da);
			viewT3D.mul(rotateT3D);
			vu.getViewTG().setTransform(viewT3D);
		}
		else if (name.equals("Yaw Right"))
		{
			rotateT3D.rotY(-da);
			viewT3D.mul(rotateT3D);
			vu.getViewTG().setTransform(viewT3D);
		}

		setTextArea();
	}


	private void move(double dz)
	{
			viewT3D.get(t3dVals);

			double xpos = t3dVals.getElement(0,3);
			double ypos = t3dVals.getElement(1,3);
			double zpos = t3dVals.getElement(2,3);

			double kx = t3dVals.getElement(0,2);
			double ky = t3dVals.getElement(1,2);
			double kz = t3dVals.getElement(2,2);

			xpos += dz*kx;
			ypos += dz*ky;
			zpos += dz*kz;

 			t3dVals.setElement(0,3,xpos);
 			t3dVals.setElement(1,3,ypos);
 			t3dVals.setElement(2,3,zpos);

			viewT3D.set(t3dVals);
			vu.getViewTG().setTransform(viewT3D);
	}


	private class ButtonAction extends AbstractAction
	{
		public ButtonAction(String s)
		{
			super(s);
			name = s;
		}
		public void actionPerformed(ActionEvent e)
		{
			buttonPressed(name);
		}
		private String name;
	}
}
