package wearable;

import javax.swing.*;
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import java.io.*;
//import com.mnstarfire.loaders3d.*;
import com.sun.j3d.utils.geometry.*;
//import amm.util.j3d.*;
import java.util.*;
import com.sun.j3d.loaders.*;
import com.sun.j3d.loaders.lw3d.*;
import com.sun.j3d.loaders.vrml97.*;
import java.net.*;

public class HelloUniverse extends JWindow
{
    static public HelloUniverse instance;
    Hashtable parts=new Hashtable();
    int counter=0;
    static Properties props=new Properties();
    static float startx=0;
    static float starty=0;
    static float startz=0;

    public void move(int n, float x, float y, float z)
    {
      System.out.println("move("+n+", "+x+", "+y+", "+z+")");
      int partnum = Integer.parseInt(props.getProperty(new Integer(n).toString()+".part"));
      TransformGroup part = getPart(partnum);
      if(part==null)
      {
        System.out.println("No part number "+n);
        return;
      }
      Transform3D trans = new Transform3D();
      Matrix3d m = new Matrix3d();
      Vector3d v = new Vector3d();
      double scale;
      part.getTransform(trans);
      scale = trans.get(m, v);
      AxisAngle4f a = new AxisAngle4f();
      int min = Integer.parseInt(props.getProperty(new Integer(n).toString()+".min"));
      int max = Integer.parseInt(props.getProperty(new Integer(n).toString()+".max"));
      x=x-min;
      if(x<0) x=0;
      x=x/max;
      a.angle=(float)(x*(Math.PI/2));
      a.x=0;
      a.y=0;
      a.z=1;
      System.out.println("a: "+a);
      m.set(a);
      trans.set(m, v, scale);
      part.setTransform(trans);
    }

    public TransformGroup getPart(int n)
    {
      return (TransformGroup)parts.get(new Integer(n));
    }

    public BranchGroup createSceneGraph() {

        BranchGroup objRoot = new BranchGroup();
        try
        {        
          Transform3D transform = new Transform3D();
          transform.setIdentity();
          transform.setScale(0.06);
          transform.setTranslation(new Vector3f(startx, starty, startz));

          TransformGroup group = new TransformGroup(transform);

          Loader loader = new VrmlLoader();
          Scene ss = loader.load("head.wrl");
          group.addChild(ss.getSceneGroup());
          objRoot.addChild(group);

          findParts(ss.getSceneGroup(), objRoot);

/*
          Transform3D xAxis = new Transform3D();
          Transform3D xAxis2 = new Transform3D();
//          xAxis.rotX(Math.PI/2);
//          xAxis2.rotX(Math.PI/2);
          Alpha alpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0, 8000, 0, 0, 0, 0, 0);
          Alpha alpha2 = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0, 8000, 0, 0, 0, 0, 0);
          TransformGroup part=getPart(27);
          TransformGroup part2=getPart(32);
          Transform3D tt=new Transform3D();
          part.getTransform(tt);
//          tt.rotX(Math.PI);
          part.setTransform(tt);
          RotationInterpolator roti = new RotationInterpolator(alpha, part, xAxis, (float)Math.PI/8, (float)Math.PI*2.0f);
          RotationInterpolator roti2 = new MyRotationInterpolator(alpha2, part2, xAxis2, 0.0f, (float)Math.PI/8);
          BoundingSphere bounds=new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0);
//          roti.setSchedulingBounds(bounds);
          roti2.setSchedulingBounds(bounds);
          objRoot.addChild(roti);
          objRoot.addChild(roti2);
*/
        }
        catch(Exception e) {e.printStackTrace();}
	return objRoot;
    }


    public HelloUniverse() {

        // now create the HelloUniverse Canvas
        getContentPane().setLayout(new BorderLayout());
        GraphicsConfiguration config =
           SimpleUniverse.getPreferredConfiguration();

        Canvas3D c = new Canvas3D(config);
        getContentPane().add("Center", c);

	// Create a simple scene and attach it to the virtual universe
	BranchGroup scene = createSceneGraph();
	SimpleUniverse u = new SimpleUniverse(c);

        TransformGroup viewTrans = u.getViewingPlatform().getViewPlatformTransform();
	u.addBranchGraph(scene);
    }


    public static void main(String[] args) throws Exception
    {
        props.load(new FileInputStream(new File("wearable.properties")));
        startx=Float.parseFloat(props.getProperty("startx"));
        starty=Float.parseFloat(props.getProperty("starty"));
        startz=Float.parseFloat(props.getProperty("startz"));
        instance=new HelloUniverse();
        Dimension size=Toolkit.getDefaultToolkit().getScreenSize();
        instance.setBounds((size.width-640)/2, (size.height-480)/2, 640, 480);
        instance.setVisible(true);
        processEvents();
    }

    static public void processEvents()
    {
      try
      {
        ServerSocket serve=new ServerSocket(5010);
        Socket socket=serve.accept();
System.out.println("Accepted connection");
        OutputStream os=socket.getOutputStream();
        InputStream is=socket.getInputStream();
        PrintWriter pw=new PrintWriter(os);
        pw.println("[Rpt=On]");
        pw.flush();
        StreamTokenizer stoke=new StreamTokenizer(new BufferedReader(new InputStreamReader(is)));
        int r=0;
        float x=0, y=0, z=0, d=0;
        while(true)
        {
          stoke.nextToken();
          if(stoke.sval==null) continue;
          else if(stoke.sval.equals("R"))
          {
            stoke.nextToken();
            stoke.nextToken();
            r=(int)stoke.nval;
          }
          else if(stoke.sval.equals("D"))
          {
            stoke.nextToken();
            stoke.nextToken();
            d=(float)stoke.nval;
//            System.out.println("d: "+d);
          }
          else if(stoke.sval.equals("X"))
          {
            stoke.nextToken();
            stoke.nextToken();
            x=(float)stoke.nval;
          }
          else if(stoke.sval.equals("Y"))
          {
            stoke.nextToken();
            stoke.nextToken();
            y=(float)stoke.nval;
          }
          else if(stoke.sval.equals("Z"))
          {
            stoke.nextToken();
            stoke.nextToken();
            z=(float)stoke.nval;
            String device=props.getProperty(new Integer(r).toString()+".part");
            if(device==null)
            {
//              System.out.println("No device found for number "+r);
              continue;
            }
            instance.move(r, x*d, y*d, z*d);
          }
//          else
//            System.out.println("sval: "+stoke.sval);
        }
      }
      catch(ConnectException e) {System.out.println("Could not connect to server.");}
      catch(Exception e) {e.printStackTrace();}
    }

  protected void findParts(Group node, Group dest)
  {
          Enumeration iterator = node.getAllChildren();
          while(iterator.hasMoreElements())
          {
            Node child=(Node)iterator.nextElement();
            if(child instanceof TransformGroup)
            {
              counter=counter+1;

              TransformGroup tg=(TransformGroup)child;
              tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
              tg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
              parts.put(new Integer(counter), tg);
              findParts(tg, null);
            }
          }
  }
}
