import vrml.*;
import vrml.node.*;
import vrml.field.*;

import java.util.*;

public class duck extends Script {

  private SFRotation duck_rot;
  private SFRotation body_rot;	
  private SFRotation lLeg_rot;
  private SFRotation rLeg_rot;
  private SFRotation lFoot_rot;
  private SFRotation rFoot_rot;
  private SFRotation lWing_rot;
  private SFRotation rWing_rot;
  private SFRotation head_rot;
  private SFRotation upLip_rot;
  private SFRotation dnLip_rot;
  private SFVec3f duck_trans;

  private SFRotation duck_rot_changed;
  private SFRotation body_rot_changed;
  private SFRotation lLeg_rot_changed;
  private SFRotation rLeg_rot_changed;
  private SFRotation lFoot_rot_changed;
  private SFRotation rFoot_rot_changed;
  private SFRotation lWing_rot_changed;
  private SFRotation rWing_rot_changed;
  private SFRotation upLip_rot_changed;
  private SFRotation dnLip_rot_changed;
  private SFRotation head_rot_changed;	

  private SFVec3f duck_trans_changed;	
	
  private float legLen;
  private float radi;
  
  private float temp_rotation[];
  private float temp_translation[];
  private float tempf;	
  private Random randGen;

  private int   phase = 1; 
  private int   count = 0;
  private int   step  = 1;


  public void initialize() {			
     duck_rot=(SFRotation)getField("duck_rot");
	 body_rot=(SFRotation)getField("body_rot");
	 lLeg_rot=(SFRotation)getField("lLeg_rot");
	 rLeg_rot=(SFRotation)getField("rLeg_rot");
	 lFoot_rot=(SFRotation)getField("lFoot_rot");
	 rFoot_rot=(SFRotation)getField("rFoot_rot");
	 lWing_rot=(SFRotation)getField("lWing_rot");
	 rWing_rot=(SFRotation)getField("rWing_rot");
	 head_rot=(SFRotation)getField("head_rot");
	 upLip_rot=(SFRotation)getField("upLip_rot");
	 dnLip_rot=(SFRotation)getField("dnLip_rot");
	 duck_trans=(SFVec3f)getField("duck_trans");
	 legLen = (float)((SFFloat)getField("legLen")).getValue();	 
	 radi = (float)((SFFloat)getField("radi")).getValue();	 

	 duck_rot_changed=(SFRotation)getEventOut("duck_rot_changed");
	 body_rot_changed=(SFRotation)getEventOut("body_rot_changed");
	 lLeg_rot_changed=(SFRotation)getEventOut("lLeg_rot_changed");
	 rLeg_rot_changed=(SFRotation)getEventOut("rLeg_rot_changed");
	 lFoot_rot_changed=(SFRotation)getEventOut("lFoot_rot_changed");
	 rFoot_rot_changed=(SFRotation)getEventOut("rFoot_rot_changed");
	 lWing_rot_changed=(SFRotation)getEventOut("lWing_rot_changed");
	 rWing_rot_changed=(SFRotation)getEventOut("rWing_rot_changed");
	 head_rot_changed=(SFRotation)getEventOut("head_rot_changed");
	 upLip_rot_changed=(SFRotation)getEventOut("upLip_rot_changed");
	 dnLip_rot_changed=(SFRotation)getEventOut("dnLip_rot_changed");
	 duck_trans_changed=(SFVec3f)getEventOut("duck_trans_changed");


	 randGen = new Random();
	 temp_rotation = new float[4];
     temp_translation = new float[3];
 	 System.out.println("INIT");
   
   
     
  }

  private void update() {
    duck_trans.getValue(temp_translation);
	duck_trans_changed.setValue(temp_translation);	

	duck_rot.getValue(temp_rotation);
	duck_rot_changed.setValue(temp_rotation);
	body_rot.getValue(temp_rotation);
	body_rot_changed.setValue(temp_rotation);
	lLeg_rot.getValue(temp_rotation);
	lLeg_rot_changed.setValue(temp_rotation);
	lFoot_rot.getValue(temp_rotation);
	lFoot_rot_changed.setValue(temp_rotation);
	lWing_rot.getValue(temp_rotation);
	lWing_rot_changed.setValue(temp_rotation);
	rLeg_rot.getValue(temp_rotation);
	rLeg_rot_changed.setValue(temp_rotation);
	rFoot_rot.getValue(temp_rotation);
	rFoot_rot_changed.setValue(temp_rotation);
	rWing_rot.getValue(temp_rotation);
	rWing_rot_changed.setValue(temp_rotation);
	head_rot.getValue(temp_rotation);
	head_rot_changed.setValue(temp_rotation);
	upLip_rot_changed.setValue(temp_rotation);
	dnLip_rot_changed.setValue(temp_rotation);
  }

  private void wing_motion(int phase){
	  if (phase == 0) {	// curve in	
		lWing_rot.getValue(temp_rotation);
		temp_rotation[3] -= 0.04f;
		lWing_rot.setValue(temp_rotation);

		rWing_rot.getValue(temp_rotation);
		temp_rotation[3] += 0.04f;
		rWing_rot.setValue(temp_rotation);
		  }
	  else { // curve out
		lWing_rot.getValue(temp_rotation);
		temp_rotation[3] += 0.04f;
		lWing_rot.setValue(temp_rotation);

		rWing_rot.getValue(temp_rotation);
		temp_rotation[3] -= 0.04f;
		rWing_rot.setValue(temp_rotation);
		  }
  }

  private void mouth_motion(int phase){
	  if (phase == 0) {	// open
		upLip_rot.getValue(temp_rotation);
		temp_rotation[3] -= 0.01f;
		upLip_rot.setValue(temp_rotation);

		dnLip_rot.getValue(temp_rotation);
		temp_rotation[3] += 0.01f;
		dnLip_rot.setValue(temp_rotation);
	  }
	  else {	// closed
		upLip_rot.getValue(temp_rotation);
		temp_rotation[3] += 0.01f;
		upLip_rot.setValue(temp_rotation);

		dnLip_rot.getValue(temp_rotation);
		temp_rotation[3] -= 0.01f;
		dnLip_rot.setValue(temp_rotation);

	  }
  }

  private void head_motion(int phase)	{
	  switch (phase) {
	  case 0:
		    // toward left
		head_rot.getValue(temp_rotation);
		temp_rotation[0]=1f;
		temp_rotation[1]=1f;
		temp_rotation[2]=1f;
		temp_rotation[3]-= 0.02f;
		head_rot.setValue(temp_rotation);
	   break;
	  case 1:
	  			// back from left
		head_rot.getValue(temp_rotation);
		temp_rotation[0]=1f;
		temp_rotation[1]=1f;
		temp_rotation[2]=1f;
		temp_rotation[3]+= 0.02f;
		head_rot.setValue(temp_rotation);
	  break;
	  case 2: // toward right
		head_rot.getValue(temp_rotation);
		temp_rotation[0]=-1f;
		temp_rotation[1]=1f;
		temp_rotation[2]=1f;
		temp_rotation[3]+= 0.02f;
		head_rot.setValue(temp_rotation);			
		  break;
	  case 3: 
			// back from right
		head_rot.getValue(temp_rotation);
		temp_rotation[0]=-1f;
		temp_rotation[1]=0f;
		temp_rotation[2]=0f;
		temp_rotation[3]-= 0.02f;
		head_rot.setValue(temp_rotation);
		break;
	  }

  }

  private void leg_start(int phase) {
	  if (phase == 0) {// left moves first
		lLeg_rot.getValue(temp_rotation);
		temp_rotation[3] += 0.05;
		lLeg_rot.setValue(temp_rotation);

		lFoot_rot.getValue(temp_rotation);
		temp_rotation[0]=0f;
		temp_rotation[1]=0f;
		temp_rotation[2]=1f;
		temp_rotation[3] -= 0.06f;
		lFoot_rot.setValue(temp_rotation);

		body_rot.getValue(temp_rotation);
		temp_rotation[3] += 0.02f;
		body_rot.setValue(temp_rotation);
	  }
	  else {   //right moves first
		rLeg_rot.getValue(temp_rotation);
		temp_rotation[3] -= 0.05;
		rLeg_rot.setValue(temp_rotation);

		rFoot_rot.getValue(temp_rotation);
		temp_rotation[0]=0f;
		temp_rotation[1]=0f;
		temp_rotation[2]=1f;
		temp_rotation[3] += 0.01f;
		rFoot_rot.setValue(temp_rotation);

		body_rot.getValue(temp_rotation);
		temp_rotation[3] -= 0.02f;
		body_rot.setValue(temp_rotation);
	  }
  }

  private void leg_step(int phase) {
	  // phase == 0: left, 1: right
	  if (phase == 0) {
		lLeg_rot.getValue(temp_rotation);
		temp_rotation[3] -= 0.05f;
		lLeg_rot.setValue(temp_rotation);

		lFoot_rot.getValue(temp_rotation);
		temp_rotation[0]=0f;
		temp_rotation[1]=0f;
		temp_rotation[2]=1f;
		temp_rotation[3]+= 0.06f;
		lFoot_rot.setValue(temp_rotation);
				  
		rLeg_rot.getValue(temp_rotation);
		temp_rotation[3] -= 0.05f;
		rLeg_rot.setValue(temp_rotation);

		rFoot_rot.getValue(temp_rotation);
		temp_rotation[0]=0f;
		temp_rotation[1]=0f;
		temp_rotation[2]=1f;
		temp_rotation[3]+= 0.06f;
		rFoot_rot.setValue(temp_rotation);

		body_rot.getValue(temp_rotation);
		temp_rotation[3] -= 0.02f;
		body_rot.setValue(temp_rotation);

		tempf = legLen*(float)Math.sin(0.05);
		duck_rot.getValue(temp_rotation);
		duck_trans.getValue(temp_translation);
		temp_translation[0] += tempf*(float)Math.cos(temp_rotation[3]);	
		temp_translation[2] -= tempf*(float)Math.sin(temp_rotation[3]);	
		duck_trans.setValue(temp_translation);
	  }
	  else {
		rLeg_rot.getValue(temp_rotation);
		temp_rotation[3] += 0.05f;
		rLeg_rot.setValue(temp_rotation);

		rFoot_rot.getValue(temp_rotation);
		temp_rotation[0]=0f;
		temp_rotation[1]=0f;
		temp_rotation[2]=1f;
		temp_rotation[3]-= 0.01f;
		rFoot_rot.setValue(temp_rotation);
				  
		lLeg_rot.getValue(temp_rotation);
		temp_rotation[3] += 0.05f;
		lLeg_rot.setValue(temp_rotation);

		lFoot_rot.getValue(temp_rotation);
		temp_rotation[0]=0f;
		temp_rotation[1]=0f;
		temp_rotation[2]=1f;
		temp_rotation[3]-= 0.06f;
		lFoot_rot.setValue(temp_rotation);

		body_rot.getValue(temp_rotation);
		temp_rotation[3] += 0.02f;
		body_rot.setValue(temp_rotation);

		tempf = legLen*(float)Math.sin(0.05);
		duck_rot.getValue(temp_rotation);
		duck_trans.getValue(temp_translation);
		temp_translation[0] -= tempf*(float)Math.cos(temp_rotation[3]);	
		temp_translation[2] -= tempf*(float)Math.sin(temp_rotation[3]);	
		duck_trans.setValue(temp_translation);	  }
  }

  private void leg_stop (int phase) {
	  if (phase == 0) {
		rLeg_rot.getValue(temp_rotation);
		temp_rotation[3] += 0.05;
		rLeg_rot.setValue(temp_rotation);

		rFoot_rot.getValue(temp_rotation);
		temp_rotation[0]=0f;
		temp_rotation[1]=0f;
		temp_rotation[2]=1f;
		temp_rotation[3]-= 0.06f;
		rFoot_rot.setValue(temp_rotation);	 
	  }
	  else {
		lLeg_rot.getValue(temp_rotation);
		temp_rotation[3] -= 0.05;
		lLeg_rot.setValue(temp_rotation);

		lFoot_rot.getValue(temp_rotation);
		temp_rotation[0]=0f;
		temp_rotation[1]=0f;
		temp_rotation[2]=1f;
		temp_rotation[3]+= 0.06f;
		lFoot_rot.setValue(temp_rotation);
	  
	  }
  }

  private void head_body_motion(int phase) {
	  // phase =0: bend forward, 1: back
	  if (phase == 0) {
	  	head_rot.getValue(temp_rotation);
		temp_rotation[0]=1f;
		temp_rotation[1]=0f;
		temp_rotation[2]=0f;
		temp_rotation[3]-= 0.02f;
		head_rot.setValue(temp_rotation);

		body_rot.getValue(temp_rotation);
		temp_rotation[0]=1f;
		temp_rotation[1]=0f;
		temp_rotation[2]=0;
		temp_rotation[3]+=0.04f;
		body_rot.setValue(temp_rotation);
	  }
	  else {
		head_rot.getValue(temp_rotation);
		temp_rotation[0]=1f;
		temp_rotation[1]=0f;
		temp_rotation[2]=0f;
		temp_rotation[3]+= 0.02f;
		head_rot.setValue(temp_rotation);

		body_rot.getValue(temp_rotation);
		temp_rotation[0]=1f;
		temp_rotation[1]=0f;
		temp_rotation[2]=0;
		temp_rotation[3]-=0.04f;
		body_rot.setValue(temp_rotation);
	  }
  }
  public void set_motion () {
	  float r ;
	  switch (phase) {
	  case 1:	
		  //step on left leg

		leg_start(0);
		wing_motion(0);
		update();
		count++;
		step ++;
		
		if (count >= 10) {
			count = 0;
			phase ++;
		}
		break;

	  case 2:
	
        leg_step(0);
		wing_motion(1);
		update();
		count++;
		if (count >= 10) {
			count = 0;
			phase ++;
		}
		break;
	  case 3:
		
		leg_stop(0);
		update();
		count++;
		if (count >= 10) {
			count = 0;
			duck_trans.getValue(temp_translation);
			if (temp_translation[0]*temp_translation[0]+
				temp_translation[2]*temp_translation[2] 
				>= radi*radi - 1) {
				phase = 10;
				break;
			}
			r = randGen.nextFloat();
			if (r < 0.5) 
				phase ++ ;
			else 
				phase = 1;
			r = randGen.nextFloat();
			if (r < 0.5) {
				duck_rot.getValue(temp_rotation);
				temp_rotation[3] += 0.02f;
				duck_rot.setValue(temp_rotation);
				duck_rot_changed.setValue(temp_rotation);
				}
		}
//			System.out.println("HEEEEE");
	  
		break;	
	  case 4:
	
        head_motion(0);
		update();
		count++;
		if (count >= 10) {
			count = 0;
			phase ++ ;

		}
		  break;
	  case 5:
	
        head_motion(1);
		update();
		count++;
		if (count >= 10) {
			count = 0;
			phase ++ ;
//			System.out.println("HEEEEE");
		}
		  break;	

	  case 6:
	
        head_motion(2);
		update();
		count++;
		if (count >= 10) {
			count = 0;
			phase ++ ;
//			System.out.println("HEEEEE");
		}
		  break;
		  
	  case 7:
	
        head_motion(3); 
		update();
		count++;
		if (count >= 10) {
			count = 0;
			r = randGen.nextFloat();
			if (r < 0.5)
			    phase ++ ;
			else 
				phase = 10;
//			System.out.println("HEEEEE");
		}
		  break;

	   case 8:
		System.out.println("HEEEEE");
	
		head_body_motion(0);
		update();
		count++;
		if (count >= 10) {
			count = 0;
			phase ++ ;
//			System.out.println("HEEEEE");
		}
		  break;
		  	   
	   case 9:
		System.out.println("HEEEEE");
	
		head_body_motion(1);
		update();
		count++;
		if (count >= 10) {
			count = 0;
			phase ++ ;
//			System.out.println("HEEEEE");
		}
		  break;
	case 10:	
	
	 leg_start(1);	
  	 update();
	 System.out.println("TETS WING");
	 System.out.println(lWing_rot_changed);
	 System.out.println(rWing_rot_changed);

		count++;
		step ++;
		
		if (count >= 10) {
			count = 0;
			phase ++;
		}

		break;
	  case 11:
	
		leg_step(1);
		wing_motion(0);

		update();
		count++;
		if (count >= 10) {
			count = 0;
			phase ++;
		}
		break;
	  case 12:

        leg_stop(1);
		wing_motion(1);
		update();
		count++;
		if (count >= 10) {
			count = 0;
			if (temp_translation[0]*temp_translation[0]+
				temp_translation[2]*temp_translation[2] 
				>= radi*radi - 1) {
				phase = 1;
				break;
			}
			r = randGen.nextFloat();
			if (r < 0.5)
				phase =1 ;
			else
				phase =10;
//			System.out.println("HEEEEE");
			r = randGen.nextFloat();
			if (r < 0.5) {
				duck_rot.getValue(temp_rotation);
				temp_rotation[3] += 0.02f;
				duck_rot.setValue(temp_rotation);
				duck_rot_changed.setValue(temp_rotation);
			}
		}
		break;	
  }
	  
}
       
  	public void processEvent(Event e) {
		
		String EventName = e.getName();
//	    System.out.print( "EVENT--");
//		System.out.println(EventName);
		if (EventName.equals("set_motion")) {
			set_motion();
		}	
	}


}