// __autor__ = Juan Carlos De Abreu R.
// __date__ = 03/13/2008
// __version__ = 1.0
//
// This file provide some functions to build the instruments
// and to manipulate it.
//

// Includes.
include("Util.snf");

// Set the path of all the geometries.
spherePath = "../Models/sphere.obj";
bodyInstrumentPartPath = "../Models/pinza2.obj";
headInstrumentPartPath = "../Models/diente2.obj";

// TODO: necesito otra esfera para pintarla cuando el se liberada de la pinza.

pinzaSphere = Model(spherePath);
bodyInstrumentPart = Model(bodyInstrumentPartPath);
headInstrumentPart = Model(headInstrumentPartPath);
leftHeadOpen = clone(headInstrumentPart);
rightHeadOpen = clone(headInstrumentPart);
leftHeadClose = clone(headInstrumentPart);
rightHeadClose = clone(headInstrumentPart);

// Defs for instrument render types.
openInstrument = 1; closeInstrument = 2; instrumentWithABall = 3;

// Set the initial instrument render mode.
displayPinza(closeInstrument);

// Function to set how the user want display the (pinza).
def displayPinza(mode) {
  if (mode == openInstrument) {
	hide(pinzaSphere);
	hide(leftHeadClose);
	hide(rightHeadClose);
	show(leftHeadOpen);
	show(rightHeadOpen);
  }
  else if (mode == closeInstrument) {
    hide(pinzaSphere);
	hide(leftHeadOpen);
	hide(rightHeadOpen);
	show(leftHeadClose);
	show(rightHeadClose);
  }
  else if (mode == instrumentWithABall) {
	hide(leftHeadClose);
	hide(rightHeadClose);
	show(pinzaSphere);
	show(leftHeadOpen);
	show(rightHeadOpen);
  }
}

// Function to set the mtl of the ball inside the pinza.
def setPinzaBallMtl(mtl) {
  pinzaSphere.setMaterial(mtl);
}

sphereLeave = Model(spherePath);
sphereLeave.draw(false);

// Function to release the sphere from the instrument.
def releaseBall(mtl) {
  // Update the position where was release the sphere.
  copy(instrumentNode.get(1).get(0), instrumentNode.get(0).get(0));
  instrumentNode.get(1).get(0).setY(instrumentNode.get(1).get(0).getY() - 0.6);
  isBallTaken = false;
  displayPinza(openInstrument);
  sphereLeave.draw(true);
  //sphereLeave.setMaterial(pinzaSphere.getMaterial());
  sphereLeave.setMaterial(mtl);
  
  // Reduce the numbre of spheres of the same color.
  tmp = prevSphere % 4;
  sphereLeft.set(tmp, sphereLeft.get(tmp) - 1);
}


// Function to create the scene node with the instrument.
instrumentNode = 0;
def buildPinzaNode() {
instrumentNode =
Group(
	Group(
			translate(0,0,0),
			rotate(0, 1, 0, 0),
			rotate(0, 0, 1, 0),
			rotate(0, 0, 0, 1),
		Group(
			
			scale(2,2,2),
			// Open instrument head part.
			Group(
				translate(0.125, 0, 0),
				rotate(9, 0, 1, 0),
				translate(0.005, 0, 0),
				rightHeadOpen
			),
			Group(
				translate(-0.125, 0, 0),
				rotate(-9, 0, 1, 0),
				translate(-0.005, 0, 0),
				rotate(180, 0, 0, 1),
				leftHeadOpen
			),
			// Close instrument head part.
			Group(
				translate(0.013, 0, 0),
				rightHeadClose
			),
			Group(
				translate(-0.013, 0, 0),
				rotate(180, 0, 0, 1),
				leftHeadClose
			),
			// Instrument body.
			Group(
				translate(0, 0, -5.8),
				scale(11,11,11),
				bodyInstrumentPart
			)
		),
		// Sphere inside the instrument.
		Group(
			translate(0, 0, 0.6),
			scale(0.7, 0.7, 0.7),
			//scale(0.2, 0.2, 0.2),
			pinzaSphere
		)
	), 
	Group(
		translate(0, 0, 0),
		scale(0.7, 0.7, 0.7),
		//scale(0.2, 0.2, 0.2),
		sphereLeave
	)
);
  return instrumentNode;
}

// Function to update the instrument position and orientation.
def updateInstrument(position, orientation) {
  setXYZ(instrumentNode.get(0).get(0), position);
  instrumentNode.get(0).get(1).setAngle(orientation.get(0) + 90);
  instrumentNode.get(0).get(2).setAngle(orientation.get(1));
  instrumentNode.get(0).get(3).setAngle(orientation.get(2));
}

// updateInstrument((0,0,0), (45, -45, -90));

// TODO:  borrar despues ....
// Keys for move the instrument.
pos = (0,0,0);
ori = (10, -30, 0);
moveStep = 0.1;

def moveInstrumentLeft() {
  pos.set(0, pos.get(0) - moveStep);
  updateInstrument(pos, ori);
}

def moveInstrumentRight() {
  pos.set(0, pos.get(0) + moveStep);
  updateInstrument(pos, ori);
}

def moveInstrumentFordward() {
  pos.set(1, pos.get(1) - moveStep);
  updateInstrument(pos, ori);
}

def moveInstrumentBackward() {
  pos.set(1, pos.get(1) + moveStep);
  updateInstrument(pos, ori);
}

def moveInstrumentUp() {
  pos.set(2, pos.get(2) - moveStep);
  updateInstrument(pos, ori);
}

def moveInstrumentDown() {
  pos.set(2, pos.get(2) + moveStep);
  updateInstrument(pos, ori);
}

setKeyFunc("I", moveInstrumentUp());
setKeyFunc("K", moveInstrumentDown());
setKeyFunc("J", moveInstrumentLeft());
setKeyFunc("L", moveInstrumentRight());
setKeyFunc("U", moveInstrumentFordward());
setKeyFunc("O", moveInstrumentBackward());

def close() {
  //displayPinza(closeInstrument);
  closeInstrument();
}

def open() {
  if (isBallTaken) {
    if (checkIfAssert())
      releaseBall(getMaterial("Green"));
	else
	  releaseBall(getMaterial("Red"));
  }
  else {
    isBallTaken = false;
    displayPinza(openInstrument);
  }
}

setKeyFunc("A", close());
setKeyFunc("Z", open());


// Function to check if the user assert in box.
def checkIfAssert() {
  if (quads.get(prevQuad).getMaterial() == pinzaSphere.getMaterial()) {
    if (collisionDetection(quads.get(prevQuad), pinzaSphere))
      return true;
  }
  return false;
}


/* 
// NOTE: esto es solo para hacer pruebas 
// luego colocar en la misma funcion anterior.
def update2(pos) {
 instrumentNode.get(0).get(0).setX(pos.get(0));
  instrumentNode.get(0).get(0).setY(pos.get(1));
  instrumentNode.get(0).get(0).setY(pos.get(2));

  setXYZ(instrumentNode.get(0).get(0), pos);
}
*/

/*
angle = 0;
def rotateTest() {
  angle = (angle + 1) % 360;
  // updateInstrument((0,0,0), (90, 0, angle));
  updateInstrument((0,0,0), (45, -45, angle));
}

Timer(10, -1, rotateTest(), rotateTest());
*/

/*
// Prueba para probar la deteccion de colisones
Material("Data/Models/Basic.mtl");
spherePath = "Data/Models/sphere.obj";

s1 = Model(spherePath);
s2 = Model(spherePath);

scene = Group(
			Group( s1 ),
			Group( translate(0,0,0), s2	)
		);

moveStep = 0.1;
def moveSphereLeft() {
  scene.get(1).get(0).setX(scene.get(1).get(0).getX() - moveStep);
}
def moveSphereRight() {
  scene.get(1).get(0).setX(scene.get(1).get(0).getX() + moveStep);
}

setKeyFunc("A", moveSphereLeft());
setKeyFunc("D", moveSphereRight());

def detect() {
  if (collisionDetection(s1, s2))
    s1.setMaterial(getMaterial("Green"));
  else 
    s1.setMaterial(getMaterial("Red"));
}
Timer(10, -1, detect(), detect());
*/
