// __autor__ = Juan Carlos De Abreu R.
// __date__ = 03/13/2008
// __version__ = 1.0
//
// This scene define an exercise for LAPAROS project.
// The exercise consist in put a ball in a box of the same color.
//

include("instrument.snf"); 

nBalls = 16;                         // Number of balls for the exercise.
putBallTime = 5000;                  // Time for put a specific ball(10 sec).
exerciseTime = nBalls * putBallTime; // Total time for do the exercise.

// TODO: el tiempo para el ejercicio no deberia ser dependiente
// del numero de esferas sino de el numero maximo de oportunidades.

hideBallTime = 2000; // Time to hide a ball after the user release the button.

// Load a material file with the basic colors.
Material("../Models/Basic.mtl");

// Path of each geometry in the scene.
quadPath = "../Models/quad.obj";
spherePath = "../Models/sphere.obj";
simuladorPath = "../Models/Simulador3.obj";

// Load each geometry.
sphereGeometry = Model(spherePath);
quadGeometry = Model(quadPath);
quadGeometry.castShadow(false);

geometrySimulador = Model(simuladorPath);
geometrySimulador.castShadow(false);


// Create a base for each color ball.
// redSphere = clone(sphereGeometry);
// greenSphere = clone(sphereGeometry);

// Set a material list.
materialList = (
//  getMaterial("Red"),
//  getMaterial("Green"),
/*    getMaterial("Blue"),
    getMaterial("Magenta"),
    getMaterial("Orange"),
    getMaterial("Yellow")
*/
	getMaterial("Orange"),
	getMaterial("Blue"),
	getMaterial("Yellow"),
    getMaterial("Magenta")
);

spheres = (); 
spheresNode = generateSpheres(spheres);

// Set the material of each geometry instance.
quadGeometry.setMaterial(getMaterial("Gray"));
// TODO: set to don't cast shadows ...

// Generate all the quads.
quads = (); quadNode = Group();
generateQuads(quads, quadNode);

sphereAux = Model(spherePath);

// Set the initial specification of the scene.
scene =
	Group(
		//Group(scale(0.7, 0.7, 0.7), sphereAux),
		Group(
			translate(0, 4.2, 0),
			rotate(-90, 1, 0, 0),
			scale(25, 25, 25),
			geometrySimulador
		),
		Group(
		//scale(0.8, 0.8, 0.8),
			Group(translate(0.5,0,-1), scale(1.2, 1.2, 1.2), quadNode),
			spheresNode,
			Group(
			//	translate(0, 1, 0),
			//	rotate(-45, 0, 0, 1), 
			//	rotate(90, 1, 0, 0),
				buildPinzaNode()
			)
		),

		Group(translate(1, 7, 12), Light()) // 0,1,2
	);
	
// updateInstrument((0,0,0), (45, -45, -90));


// Set the camera position.
camera = Camera();
camera.setPos(0, 8, 10);
camera.setActive();
//camera.rotateY(10);

def generateQuads(quadList, node) {
  // Create all the instaces of the quads.
  for (i = 0; i < 8; ++i) {
    for (j = 0; j < 8; ++j) {
	  newQuad = clone(quadGeometry);
	  quadList.add(newQuad);
      node.add( Group(
					translate(i - 4, -0.4, j - 4),
					rotate(-90, 1, 0, 0), scale(0.95, 0.95, 0.95),
					newQuad
				));
	}
  }
}

// Function to put all the balls in a scene node and a list(to can access easy).
 
def generateSpheres(spheres) {
  // 
  sphereMtl1 = clone(sphereGeometry);
  sphereMtl2 = clone(sphereGeometry);
  sphereMtl3 = clone(sphereGeometry);
  sphereMtl4 = clone(sphereGeometry);
  sphereMtl1.setMaterial(materialList.get(0));
  sphereMtl2.setMaterial(materialList.get(1));
  sphereMtl3.setMaterial(materialList.get(2));
  sphereMtl4.setMaterial(materialList.get(3));

  // Create all the instances of the spheres.
  // Add each instance to the sphereList and sceneNode.
  node = Group();
  for (i = 0; i < 2; ++i) {
    for (j = 0; j < 2; ++j) {
	  newSphereMtl1 = clone(sphereMtl1);
	  newSphereMtl2 = clone(sphereMtl2);
	  newSphereMtl3 = clone(sphereMtl3);
	  newSphereMtl4 = clone(sphereMtl4);
	  
      node.add( Group(translate(i - j*2, -0.2, i - 7.5), scale(0.7, 0.7, 0.7), newSphereMtl1) );
	  node.add( Group(translate(i - 6.2, -0.2, i - j*2), scale(0.7, 0.7, 0.7), newSphereMtl2) );
	  node.add( Group(translate(i - j*2, -0.2, 4 + i), scale(0.7, 0.7, 0.7), newSphereMtl3) );
	  node.add( Group(translate(5 + i, -0.2, i - j*2), scale(0.7, 0.7, 0.7), newSphereMtl4) );
	  
	  spheres.add( newSphereMtl1 );
	  spheres.add( newSphereMtl2 );
	  spheres.add( newSphereMtl3 );
	  spheres.add( newSphereMtl4 );
	}
  }
  return node;
}

// TODO: para la seleccion de los colores se deberia tomar en cuanta
// el color de las spheras que quedan, de tal manera de no generar
// colores de esferas que no se tienen...
// Function to change the box that has the focus now.
prevQuad = 0;
def changeQuad() {
  // Restore default material.
  quads.get(prevQuad).setMaterial(getMaterial("Gray"));
  
  // Set the focus material to a new quad.
  newFocusQuad = INT(rand(0, 64));
  //materialToUse = materialList.get(INT(rand(0, 4)));
  materialToUse = randMtlQuad();
  quads.get(newFocusQuad).setMaterial(materialToUse);
  prevQuad = newFocusQuad;
}
Timer(putBallTime, -1, changeQuad(), changeQuad());


// Functions to check if the user take or leave a ball.

isBallTaken = false; // To know if the instrument have a ball.

// This method manage the event when the user press the botton of the
// raster; that means open the instrument.
def openInstrument() {
  if (isBallTaken) {
    isBallTaken = false;
	// Get the ball taken.
	ballTaken = ();
	if (collisionDetection(quads.get(prevQuad), ballTaken)) {
	  // TODO: verificar que los materiales sean los mismos.
      ballTaken.setMaterial(getMaterial("Green"));
	  print("Correct");
    }
	else {
	  ballTaken.setMaterial(getMaterial("Red"));
      print("Incorrect");
    }
	Timer(hideBallTime, hideBallTime, hide(ballTaken), hide(ballTaken));
  }
}

def touchASphere() {
  // Check if the user get a sphere.
  nSpheres = spheres.size();
  for (i = 0; i < nSpheres; ++i) {
    spherei = spheres.get(i);
	if (spherei.isEnable()) {
	  //print("entro" + STRING(i));
	  if (collisionDetection(spherei, pinzaSphere)) return i;
	}
  }
  return -1;
}

/*
def detect() {
  aux = touchASphere();
  if (aux != -1)
    sphereAux.setMaterial(getMaterial("Green"));
  else 
    sphereAux.setMaterial(getMaterial("Red"));
}
Timer(10, -1, detect(), detect());
*/

prevSphere = 0;
def closeInstrument() {
  if (isBallTaken) return 0;
  sphereIndex = touchASphere();
  //print(sphereIndex);
  if (sphereIndex != -1) {
    isBallTaken = true;
	prevSphere = sphereIndex;
	displayPinza(instrumentWithABall);
	spherei = spheres.get(sphereIndex);
	spherei.draw(false);
	setPinzaBallMtl(spherei.getMaterial());
  }
  else {
    displayPinza(closeInstrument);
  }
}


// Function get a random mtl for a quad.
//   The function return a mtl if exist unless one sphere with the same color
sphereLeft = (4, 4, 4, 4);
def randMtlQuad() {
  if (sphereLeft == (0, 0, 0, 0))
    return getMaterial("Gray"); // TODO: exit the app.
  initialPos = INT(rand(0, 4));
  for (i = 0; i < 4; ++i)
    if (sphereLeft.get(initialPos + i) > 0)
      return materialList.get(initialPos + i);
}
