//Tunnel where everything happens


var Tunneli = function(){
  //kantaluokan rakentajan kutsu
  PartBase.call(this);
  
  this.lightsRotationSpeed = 0.05;
  this.offsetSpeed = -0.05;
  this.fadeSpeed = 2;
  this.cats_fadedOut = false;
  this.cats_fadedIn = false;
  this.ball_fadedOut = false;
  
  this.initScene();
}

Tunneli.prototype = PartBase.prototype.inheritance();

//scene is initialized before demo starts
Tunneli.prototype.initScene = function(){
  PartBase.prototype.initScene.call(this);
  
  this.camera.position.z = 400;
  this.scene.add(this.camera);
  
  this.ball_z = 310;
  this.cats_z = 300;
  
  this.lights = new THREE.Object3D();
  this.createLights(5);
  this.scene.add(this.lights);
  this.createTunnel();

  this.createBall();
  this.createCats();
};


//Operations that takes place in fixed timestep, 30FPS
Tunneli.prototype.animateTunnel = function(timeStep, elapsedTime){
  this.tunnelTexture.offset.y += this.offsetSpeed;
  this.tunnelTexture.offset.y %= 1;
  this.tunnelTexture.needsUpdate = true;
  
  this.lights.rotation.z += this.lightsRotationSpeed;
};

Tunneli.prototype.animateBall = function(timeStep, elapsedTime){
  this.shader.uniforms.time.value = elapsedTime;
  this.ball.position.z += Math.sin(elapsedTime)*0.8;
};

Tunneli.prototype.animateCats = function(timeStep, elapsedTime) {
  for(var i=0; i<this.catArray.length; i++) {
    var c = this.catArray[i];
    c.position.y = (Math.sin(elapsedTime)*(c.position.z*0.2+2)+Math.cos(elapsedTime)*(0.2*c.position.x-2));
  }
};

Tunneli.prototype.moveCats = function(timeStep, elapsedTime) {
  if(this.catArray[2].position.z < 50) {
    this.catArray[0].position.x -=0.3;
    this.catArray[6].position.x +=0.3;
  
    this.catArray[0].position.z +=1;
    this.catArray[6].position.z +=0.8;

    this.catArray[2].position.x -=0.1;
    this.catArray[8].position.x +=0.1;
  
    this.catArray[2].position.z +=0.4;
    this.catArray[8].position.z +=0.3; 
  }
};

Tunneli.prototype.animate = function(timeStep, elapsedTime){
  PartBase.prototype.animate.call(this, timeStep, elapsedTime);
  this.animateTunnel(timeStep, elapsedTime);
  this.animateBall(timeStep, elapsedTime);
};

Tunneli.prototype.animate2 = function(timeStep, elapsedTime){
  PartBase.prototype.animate.call(this, timeStep, elapsedTime);
  this.animateTunnel(timeStep, elapsedTime);
  
  if(!this.ball_fadedOut){
    this.shader.uniforms.time.value = elapsedTime;
    this.ball.position.y += Math.sin(elapsedTime);
    this.ball_fadedOut = this.fadeOut(this.ball);
  }
  if(!this.cats_fadedIn){
    this.cats_fadedIn = this.fadeIn(this.cats, this.cats_z);
  }
  else{
    this.cats.position.z += Math.sin(elapsedTime)*0.8;
  }
  this.animateCats(timeStep, elapsedTime);  
};

Tunneli.prototype.animate3 = function(timeStep, elapsedTime){
  PartBase.prototype.animate.call(this, timeStep, elapsedTime);
  this.animateTunnel(timeStep, elapsedTime);
  if(!this.ball_fadedOut){
    this.shader.uniforms.time.value = elapsedTime;
    this.ball.position.y += Math.sin(elapsedTime);
    this.ball_fadedOut = this.fadeOut(this.ball);
  }
  if(!this.cats_fadedIn){
    this.cats_fadedIn = this.fadeIn(this.cats, this.cats_z);
  }
  else{
    this.cats.position.z += Math.sin(elapsedTime)*0.8;
  }
  this.animateCats(timeStep, elapsedTime);
  this.moveCats(timeStep, elapsedTime);
};

Tunneli.prototype.animate4 = function(timeStep, elapsedTime){
  PartBase.prototype.animate.call(this, timeStep, elapsedTime);
  this.animateTunnel(timeStep, elapsedTime);
  if(!this.ball_fadedOut){
    this.shader.uniforms.time.value = elapsedTime;
    this.ball.position.y += Math.sin(elapsedTime);
    this.ball_fadedOut = this.fadeOut(this.ball);
  }
  if(!this.cats_fadedOut){
    this.animateCats(timeStep, elapsedTime);
    this.moveCatsMore(timeStep, elapsedTime);
  }
};

Tunneli.prototype.moveCatsMore = function(timeStep, elapsedTime) {
  for (var i=0; i<this.catArray.length; i++) {    
    this.cats_fadedOut = this.fadeOut(this.catArray[i]);    
  }
}

Tunneli.prototype.fadeIn = function(obj, endPos){
  if(!obj.visible){
    obj.visible = true;
  }
  obj.position.z += this.fadeSpeed;
  if(obj.position.z >= endPos){
	obj.position.z = endPos;
    return true;
  }
  return false;
};

Tunneli.prototype.fadeOut = function(obj){
  obj.position.z += this.fadeSpeed;

  if(obj.position.z >= 1000){
    obj.visible = false;
    return true;
  }
  return false;
};

Tunneli.prototype.createTunnel = function(){
  THREE.ImageUtils.crossOrigin = true;
  this.tunnelTexture = THREE.ImageUtils.loadTexture( rainbow );
  this.tunnelTexture.wrapS = THREE.RepeatWrapping;
  this.tunnelTexture.wrapT = THREE.RepeatWrapping;
  this.tunnelTexture.repeat.set(1,8);

  var cylinder = new THREE.CylinderGeometry(40, 10, 800, 128, 128, true);
  var material = new THREE.MeshPhongMaterial({
    ambient : 0xC0D9D9,
    emissive : 0xC1CDCD,
    specular : 0x668B8B,
    shininess: 80,
    map : this.tunnelTexture,
    side: THREE.BackSide
  });
  
  this.mesh = new THREE.Mesh(cylinder, material);
  this.mesh.rotation.x = Math.PI/2;
  this.scene.add(this.mesh);  
};

Tunneli.prototype.createCats = function() {
  this.cats = new THREE.Object3D();
  this.catArray = [];
  
  var c = cat();

  for(var i=(-1); i<2; i++) {
    for (var j = (-1); j<2; j++) {
      this.cloneCat(i*15, j*30, c);
    }
  }
   
  this.cats.position.z = -200;
  this.scene.add(this.cats);
  this.cats.visible.false;
}

Tunneli.prototype.cloneCat = function(posX, posZ, cat) {
  var c = cat.clone();
  c.rotation.y = Math.PI/2;
  c.position.x =+ posX; 
  c.position.z = posZ;
  this.cats.add(c);
  this.catArray.push(c);
}

Tunneli.prototype.createBall = function(){
  
  var ambient = new THREE.AmbientLight(0xFAF0F6);
  this.scene.add(ambient);
  
  this.shader = VertexDisplacementShader();
  this.shader.uniforms.texture.value = this.tunnelTexture;
  
  var displaceMaterial = new THREE.ShaderMaterial({
    uniforms : this.shader.uniforms,
    vertexShader : this.shader.vertexShader,
    fragmentShader : this.shader.fragmentShader
  });
  
  this.ball = new THREE.Mesh(new THREE.IcosahedronGeometry(8, 4), displaceMaterial);
  this.ball.position.z = this.ball_z;
  this.scene.add(this.ball);
};

Tunneli.prototype.createLights = function(lights_amount){
  
  var r = 40;
  var delta = 2*Math.PI/lights_amount;
  var alpha = 0;
  
  for(var i = 0; i < lights_amount; ++i){
    
    var light = new THREE.PointLight(0xCDC9C9);
    
    light.position.z = 300;
    light.position.y = Math.sin(alpha)*r;
    light.position.x = Math.cos(alpha)*r;
    
    var light2 = new THREE.PointLight(0xEEDC82);
    light2.position.z = -250;
    light2.position.y = Math.sin(alpha)*r;
    light2.position.x = Math.cos(alpha)*r;
    
    this.lights.add(light);
    this.lights.add(light2);
    
    alpha += delta;
  }
};

