/*

 Project I

 Name:    Phuc  Nguyen        SID: 13547274         Login: cs184-dh
          Danny Ho			  SID: 12517699			Login: cs184-dl

*/

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


public class control extends Script {

	// Event out
	private  SFVec3f setA_translation;  ////////////////////////////
	private  SFVec3f setB_translation;	//
	private  SFVec3f setC_translation;	//
	private  SFInt32 help_changed;		// Output events
	private  SFVec3f SetA_Scaling;		//
	private  SFVec3f SetB_Scaling;		//
	private  SFVec3f SetC_Scaling;		////////////////////////////

	private int parent;	// if 1, then A is the parent; if 2, then B is the parent; if 3, C is the parent.
	private int child;	// if 1, then A is the child; if 2, then B is the child; if 3, C is the child.
	private int i;

	private  boolean A_parent_B; // True if A is the parent of B
	private  boolean B_parent_A; // True if B is the parent of A 
	private  boolean A_parent_C; // True if A is the parent of C
	private  boolean C_parent_A; // True if C is the parent of A
	private  boolean C_parent_B; // True if C is the parent of B
	private  boolean B_parent_C; // True if B is the parent of C
	private  boolean scaling;	 // True if now is in scaling mode
	private  boolean chooseParent; // True if the parent button is pressed
	private  boolean chooseChild;  // True if the child button is pressed

	private  float translation[];	// temp storage for the translation value coming in
	private  float newTrans[];		//  ...
	private ConstSFVec3f tempTrans; // temp storage for the translation value coming in

	private SFInt32 choice;

// This will get called when the script node get called.
public void initialize(){
	 setA_translation = (SFVec3f) getEventOut("SetA_translation");
	 setB_translation = (SFVec3f) getEventOut("SetB_translation");
	 setC_translation = (SFVec3f) getEventOut("SetC_translation");

	 SetA_Scaling = (SFVec3f) getEventOut("SetA_Scaling");
	 SetB_Scaling = (SFVec3f) getEventOut("SetB_Scaling");
	 SetC_Scaling = (SFVec3f) getEventOut("SetC_Scaling");

	 help_changed = (SFInt32) getEventOut("help_changed");
	 choice = (SFInt32) getField("choice");

	 chooseParent = false;
	 chooseChild = false;

	 parent = 0;
	 child = 0;

	 A_parent_B = false;
	 B_parent_A = false;
	 A_parent_C = false;
	 C_parent_A = false;
	 C_parent_B = false;
	 B_parent_C = false;

	 translation = new float[3];
	 newTrans = new float[3];
	 scaling = false;
	 System.out.println("Finish intializing - version A");

}

// Change the translation on A and all its children
private void ATranslation_changed(float trans[]) {

	setA_translation.setValue(trans);
	if (A_parent_B == true) {
	  setB_translation.setValue(trans); }

	if ((A_parent_C == true) || ((A_parent_B == true) && (B_parent_C == true)))
	 {
		  setC_translation.setValue(trans); }
}

// Change the translation on B and all its children
private void BTranslation_changed(float trans[]) {

  setB_translation.setValue(trans);

  if (B_parent_A == true) {
		  setA_translation.setValue(trans); }
  if ((B_parent_C == true) || ((B_parent_A == true) && (A_parent_C ==true)))
  {
		 setC_translation.setValue(trans); }
}

// Change the translation on C and all its children
private void CTranslation_changed(float trans[]) {

  setC_translation.setValue(trans);

  if (C_parent_A == true) {
		  setA_translation.setValue(trans); }
  if ((C_parent_B == true) || ((C_parent_A == true) && (A_parent_B == true))) {
		 setB_translation.setValue(trans); }

}

// Change the scale on A and all its children
private void AScale_changed(float trans[]) {

	SetA_Scaling.setValue(trans);
	if (A_parent_B == true)
	  SetB_Scaling.setValue(trans);

	if ((A_parent_C == true) || ((A_parent_B == true) && (B_parent_C == true)))
	 {
		  SetC_Scaling.setValue(trans); }
}

// Change the scale on B and all its children
private void BScale_changed(float trans[]) {

  SetB_Scaling.setValue(trans);

  if (B_parent_A == true) {
		  SetA_Scaling.setValue(trans); }
  if ((B_parent_C == true) || ((B_parent_A == true) && (A_parent_C ==true)))
  {
		 SetC_Scaling.setValue(trans); }
}

// Change the scale on C and all its children
private void CScale_changed(float trans[]) {

  SetC_Scaling.setValue(trans);

  if (C_parent_A == true)
		  SetA_Scaling.setValue(trans);
  if ((C_parent_B == true) || ((C_parent_A == true) && (A_parent_B == true)))
		 SetB_Scaling.setValue(trans);

}

// Assigning parent or children of one node
private void set_node(int node) {
  if (chooseParent == true) {
	  parent = node;
		chooseParent = false; }
	else if (chooseChild == true) {
	  child = node;
		chooseChild = false; }
}

// Attaching objects takes place here
private void attach() {
	if (parent == 1) {
		 if (child == 2)
			  A_parent_B = true;
		 else if (child == 3)
			  A_parent_C = true;
	 }
	 else if (parent == 2) {
		  if (child == 1)
				B_parent_A = true;
			else if (child == 3)
				B_parent_C = true;
	  }
	 else if (parent == 3) {
		  if (child == 1)
				C_parent_A = true;
			else if (child == 2)
				C_parent_B = true;
	 }
		// reset parent & child
		parent = 0;
		child = 0;
}

// Detach all objects relationship.
private void detach() {
	A_parent_B = false;
	B_parent_A = false;
	A_parent_C = false;
	C_parent_A = false;
	C_parent_B = false;
	B_parent_C = false;
}

// Display help menu
private void set_help(boolean bval) {
	if (bval == true) {
	  i = (choice.getValue() + 1) % 2;
	  choice.setValue(i);
	  help_changed.setValue(i);
	}
}

// Catch an event and dispatch to an appropraite function
public void processEvent(Event e){
  String EventName = e.getName();

  if (EventName.equals("ATranslation_changed"))  {
	  tempTrans = (ConstSFVec3f) e.getValue();
	  tempTrans.getValue(translation);
	  ATranslation_changed(translation);
		}

  else if (EventName.equals("BTranslation_changed")) {
	 tempTrans = (ConstSFVec3f) e.getValue();
	 tempTrans.getValue(translation);
	 BTranslation_changed(translation);
	 }

	else if (EventName.equals("CTranslation_changed")) {
	 tempTrans = (ConstSFVec3f) e.getValue();
	 tempTrans.getValue(translation);
	 CTranslation_changed(translation);
	 }

	else if (EventName.equals("set_parent"))
		chooseParent = true;

	else if (EventName.equals("set_child"))
		chooseChild = true;

	else if (EventName.equals("set_nodeA"))
		set_node(1);

	else if (EventName.equals("set_nodeB"))
	  set_node(2);

	else if (EventName.equals("set_nodeC"))
		set_node(3);

	else if (EventName.equals("attach"))
		attach();

	else if (EventName.equals("detach"))
		detach();

	else if (EventName.equals("set_help"))
		set_help(((ConstSFBool) e.getValue()).getValue());

	else if (EventName.equals("scaling"))
		if (((ConstSFBool) e.getValue()).getValue() == true)
		  scaling = !scaling;

	if (scaling == true)
		if (EventName.equals("AScale_changed")) {
		  tempTrans = (ConstSFVec3f) e.getValue();
		  tempTrans.getValue(translation);
		  AScale_changed(translation); }

		else if (EventName.equals("BScale_changed")) {
		  tempTrans = (ConstSFVec3f) e.getValue();
		  tempTrans.getValue(translation);
		  BScale_changed(translation); }

		else if (EventName.equals("CScale_changed")) {
		  tempTrans = (ConstSFVec3f) e.getValue();
		  tempTrans.getValue(translation);
		  CScale_changed(translation); }
 }
}