var Scene = (function() {
  var lerp = function(s, e, p) {
    return s - ((s - e) * p);
  }
  
  var wiggleCoordinates = function(geo, dist, seed)
  {
    for (var i=0; i < geo.vertices.length; i++)
    {
      Math.seedrandom(geo.vertices[i].x+geo.vertices[i].y+geo.vertices[i].z);
        geo.vertices[i].x += (Math.random()-0.5)*dist;
        geo.vertices[i].y += (Math.random()-0.5)*dist;
        geo.vertices[i].z += (Math.random()-0.5)*dist;
    }
    geo.computeFaceNormals();
    geo.computeVertexNormals();
  }

  return {

    id: getIdForLastLoadedScript(),
    load: function()
    {
      this.scene = new THREE.Scene();
      
      var rockMat = new THREE.MeshLambertMaterial({
        //ambient: #999999,
        color: 0xA0A09F,
        //emissive: #222222,
        shading: THREE.FlatShading
      });
      
      this.neger = new THREE.MeshBasicMaterial({
        //ambient: #999999,
        color: 0x000000,
        //emissive: #222222,
        shading: THREE.FlatShading
      });
      
      
      var $this = this;
      var loader = new THREE.JSONLoader();
      loader.load( 'models/hell.js', function ( geometry, materials ) {
        wiggleCoordinates(geometry, 5, 3434);
        $this.mesh = new THREE.Mesh( geometry, rockMat );
        $this.mesh.scale.set(1, 1, 1);
        $this.scene.add($this.mesh);
      });
      
      this.piglight1 = new THREE.PointLight( 0xff1000, 1, 40 );
      this.piglight1.position.set( 1000,1000,1000 );
      this.piglight2 = new THREE.PointLight( 0xff1000, 1, 40 );
      this.piglight2.position.set( 1000,1000,1000 );
      this.piglight3 = new THREE.PointLight( 0xff1000, 1, 40 );
      this.piglight3.position.set( 1000,1000,1000 );
      this.piglight4 = new THREE.PointLight( 0xff1000, 1, 40 );
      this.piglight4.position.set( 1000,1000,1000 );
      this.scene.add( this.piglight1 );
      this.scene.add( this.piglight2 );
      this.scene.add( this.piglight3 );
      this.scene.add( this.piglight4 );
      
      
      
      //var bglight = new THREE.AmbientLight(0xFF6611); // soft red light
      //this.scene.add(bglight);

      //      var light = new THREE.HemisphereLight( 0xff7a81, 0x000000, .5 );
      var light = new THREE.HemisphereLight( 0xFF6611, 0x000000, .1 );
      light.position.y = 100;
      light.position.z = -100;
      light.position.x = -100;

    //  this.scene.add( light );
      this.gl = [];
      
      // Lava glowlight:
      var glowlights = 0;
      for(i=0;i<10;i++){
        for(j=0;j<10;j++) {
          var pl = new THREE.PointLight( 0xff0000, 2, 200 );
          pl.position.set( (i-5)*200, 100, (j-5)*200 );
          this.scene.add( pl );
          this.gl.push(pl);
        }
      }
      // Ambient pointlight:
      this.pl = new THREE.PointLight( 0xff0000, 0.4, 0 );
      this.pl.position.set( 0, 400, 0 );
      this.scene.add( this.pl );
      /* LAVA */
      tex.lavatex = load_texture(texture_dir+'lava.png','Lava');
      tex.lavatex.wrapS = THREE.RepeatWrapping;
      tex.lavatex.wrapT = THREE.RepeatWrapping;
      tex.lavatex.repeat.set(5,5);
      
//      this.lavaMat = new THREE.MeshLambertMaterial({
      this.lavaMat = new THREE.MeshBasicMaterial({
        //ambient: #999999,
        //color: 0xFF0000,
        //vertexColors: THREE.FaceColors,
        map: tex.lavatex,
        
        //emissive: #222222,
        shading: THREE.FlatShading
      });
      
      /* LAVA MASK */
      tex.lavamtex = load_texture(texture_dir+'lavamask.png','LavaMask');
      tex.lavamtex.wrapS = THREE.RepeatWrapping;
      tex.lavamtex.wrapT = THREE.RepeatWrapping;
      tex.lavamtex.repeat.set(5,5);
      this.lavaMaskMat = new THREE.MeshBasicMaterial({
        //ambient: #999999,
        //color: 0xFF0000,
        //vertexColors: THREE.FaceColors,
        map: tex.lavamtex,
        
        //emissive: #222222,
        shading: THREE.FlatShading
      });
            
      
      
      this.lavaGeometry = new THREE.PlaneGeometry(1300,1300, 50,50)
      this.lavaGeometry.applyMatrix(new THREE.Matrix4().makeRotationX(deg2rad(-90)));
      
      this.lava = new THREE.Mesh(this.lavaGeometry, this.lavaMat);
      this.lava.position.y += 80;
      this.scene.add(this.lava);
      
      
      // Add flying pig
      this.pig = new THREE.Pig({center:true});
      this.pig.scale.set(5, 5, 5);
      this.pig.position.set(1000,1000,1000);
      this.scene.add(this.pig);
      

      
      /*
      //  this.axishelper = new THREE.AxisHelper(5); this.scene.add(this.axishelper);

      var sola = new THREE.DirectionalLight( 0x777777, 1);
      sola.color.setHSL( 0.1, 0.7, 0.7);
      sola.castShadow = true;
      sola.shadowDarkness = 0.5;
      //sola.shadowCameraVisible = true;
      sola.position.set(30,30,30);
      sola.shadowCameraNear = 0;
      sola.shadowCameraFar = 100;

      var d = 20;
      sola.shadowCameraLeft = -d;
      sola.shadowCameraRight = d;
      sola.shadowCameraTop = d;
      sola.shadowCameraBottom = -d;
      sola.shadowMapWidth = 2048;
      sola.shadowMapHeight = 2048;
      //this.scene.add( new THREE.DirectionalLightHelper(sola, 0.2) );

      this.scene.add(sola);

      var mat = new THREE.MeshLambertMaterial({
        ambient: 0x999999,
        color: 0x11aF44,
        emissive: 0x001100,
        shading: THREE.FlatShading
        //wireframe: true
      });

      var ground = new THREE.Mesh(
        new THREE.BoxGeometry( 1000, .1, 1000 ),
        mat
      );

      ground.receiveShadow = true;
      this.scene.add(ground);
*/
      this.composer = new THREE.EffectComposer(renderer);

      this.camera = new THREE.PerspectiveCamera(90, 16/9, 0.1, 2000);
      this.camera.position.set(-350, 350, -350);
      this.camera.lookAt(new THREE.Vector3(150, 0, 0));

      controls = new THREE.OrbitControls( this.camera );
      controls.addEventListener( 'change', render );

      this.meatgrinder = new THREE.MeatGrinder();
      this.meatgrinder.rotation.z = Math.PI/2;
      this.meatgrinder.position.y = 10;
      this.meatgrinder.scale.set(10,10,10);
      this.meatgrinder.translateX(180);  // UP (WTF)
      this.meatgrinder.translateY(-105);
      this.meatgrinder.translateZ(380);
      this.meatgrinder.rotateOnAxis(new THREE.Vector3(1,0,0), -Math.PI/2);
      this.scene.add(this.meatgrinder);
      
      var pigPoints = [
        new THREE.Vector3(25,230,-500),
        new THREE.Vector3(0,200,-100),
        new THREE.Vector3(300,150,100),
        new THREE.Vector3(450,300,-300),
        new THREE.Vector3(330,250,-290),
        new THREE.Vector3(250,230,-150),
        new THREE.Vector3(0,250,0),
        new THREE.Vector3(-150,260,300),
        new THREE.Vector3(80,280,320),
        new THREE.Vector3(110,200,320),
      ]
      
      var lineMaterial = new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 2 } );
      this.pigSpline = new THREE.SplineCurve3(pigPoints);
      this.pigPath = new THREE.Geometry();
      this.pigPath.vertices = this.pigSpline.getPoints(250);
      this.path = new THREE.Line(this.pigPath, lineMaterial);
      //this.scene.add(this.path);
  
      this.axishelper = new THREE.AxisHelper(5);
      this.axishelper.position.y = 250;
      //this.scene.add(this.axishelper);
      
      this.baconshower = new THREE.BaconShower(
        new THREE.Vector3(105,183,310),
        new THREE.Vector3(105,200,200),
        new THREE.Vector3(105,0,200));
      this.scene.add(this.baconshower);
      
/*


			this.pig = new THREE.Pig();
//			this.pig.scale.x = this.pig.scale.y = this.pig.scale.z = 0.04;
			this.pig.rotation.y = Math.PI;
			this.pig.rotation.z = Math.PI;
			this.pig.position.y = 1;
			this.pig.position.x = -6;
			this.pig.position.y = 20;
			this.pig.castShadow = true;
			this.scene.add(this.pig);






      */
      // SSAO Depth
      this.depthShader = THREE.ShaderLib[ "depthRGBA" ];
      this.depthUniforms = THREE.UniformsUtils.clone( this.depthShader.uniforms );

      this.depthMaterial = new THREE.ShaderMaterial({
        fragmentShader: this.depthShader.fragmentShader,
        vertexShader: this.depthShader.vertexShader,
        uniforms: this.depthUniforms
      });
      this.depthMaterial.blending = THREE.NoBlending;

      this.depthTarget = new THREE.WebGLRenderTarget( wWidth, wHeight, {
        minFilter: THREE.NearestFilter,
        magFilter: THREE.NearestFilter,
        format: THREE.RGBAFormat
      });
      
      
      this.copyPass = new THREE.TexturePass(buffer1);
      this.composer.addPass(this.copyPass);
      
      this.BloomPass = new THREE.BloomPass(3,25,100,1024);
      this.composer.addPass(this.BloomPass);
      
      this.savePass = new THREE.SavePass(buffer1);
      this.composer.addPass(this.savePass);
      

      this.renderPass = new THREE.RenderPass(this.scene, this.camera);
      this.composer.addPass(this.renderPass);


      this.SSAOPass = new THREE.ShaderPass( THREE.SSAOShader );
      this.SSAOPass.uniforms[ 'tDepth' ].value = this.depthTarget;
      this.SSAOPass.uniforms[ 'size' ].value.set( wWidth * 0.75, wHeight * 0.75 );
      this.SSAOPass.uniforms[ 'cameraNear' ].value = this.camera.near;
      this.SSAOPass.uniforms[ 'cameraFar' ].value = this.camera.far;
      this.SSAOPass.uniforms[ 'aoClamp' ].value = 0.5;
      this.SSAOPass.enabled = true;
      this.composer.addPass( this.SSAOPass );

      this.blendPass = new THREE.ShaderPass(THREE.AdditiveBlendShader2);
      this.blendPass.uniforms['tDiffuse2'].value = buffer1;
      this.composer.addPass(this.blendPass);
      
      this.composer.addPass(final_pass);

    },

    render: function(time, percent)
    {
      this.meatgrinder.animate(time);
      this.baconshower.animate(getVal('var4'), getVal('var5'));
      this.controlCamera(this.camera);
      var p = getVal('percent');

      if(p < 0) {
        p = 0;
      }
      var pigPos = this.pigSpline.getPointAt(p/100);
      this.pig.position.set(pigPos.x, pigPos.y, pigPos.z);
      this.piglight1.position.set(pigPos.x-25, pigPos.y-25, pigPos.z-10);
      this.piglight2.position.set(pigPos.x+25, pigPos.y-25, pigPos.z);
      this.piglight3.position.set(pigPos.x-25, pigPos.y-25, pigPos.z-10);
      this.piglight4.position.set(pigPos.x, pigPos.y+25, pigPos.z);
      this.pig.rotation.set(p*0.8/4,p/4,p*1.2/4);
      var pigScale = getVal("var1");
      this.pig.visible = (pigScale > 0.0001);
      this.pig.scale.set(pigScale, pigScale, pigScale);

      // ANimate lights!
      for (var i=0; i < this.gl.length; i++){
       this.gl[i].position.y  = 100 + ((Math.sin(time*5+i)+1)*10)
      }
      
      Math.seedrandom(time);
      time = time *1.0001;



      /*
      renderer.shadowMapEnabled = true;
      renderer.shadowMapType = THREE.PCFSoftShadowMap;
      this.meatgrinder.setAge(getVal('var2'))
      if(this.pig){
        this.pig.position.y = getVal('var3');
        this.pig.scale.x = this.pig.scale.y = this.pig.scale.z = getVal('var4')*10;
      }

      this.baconshower.anim(getVal('var5'), percent);

      */
      /* Animate lava */
      for (var fi=0; fi < this.lavaGeometry.faces.length; fi++)
      {
        f = this.lavaGeometry.faces[fi];
        this.lavaGeometry.faces[fi].color.setRGB(1,(Math.sin(fi+time)+1)/6,0); // #AF6200
    
        //this.planeGeometry.faces[i].color.setRGB(Math.random(), Math.random(), Math.random());
        
      }
      for (var i=0; i < this.lavaGeometry.vertices.length; i++){
        y = this.lavaGeometry.vertices[i].y;
        x = this.lavaGeometry.vertices[i].x;
        z = this.lavaGeometry.vertices[i].z;
        this.lavaGeometry.vertices[i].y = noise.perlin3(i*10.1,time,z/22.3)*10;// noise.perlin3(x, z, time)*1000;
//        this.lavaGeometry.vertices[i].z += Math.sin((i + time)*10)/200;
//        this.lavaGeometry.vertices[i].x += Math.sin(22.1 + (i + time)*10)/200;
        //if(i == 0)
        //  console.log(time);
        //console.log(noise.perlin3(x, z, time));
      }
      this.lavaGeometry.colorsNeedUpdate = true;
      this.lavaGeometry.verticesNeedUpdate = true;
      this.lavaGeometry.computeFaceNormals();
      this.lavaGeometry.computeVertexNormals();
      
      
      this.camera.fov = getVal('var7');
      this.camera.aspect = 16/9;
      this.camera.updateProjectionMatrix();
      this.scene.overrideMaterial = this.depthMaterial;
      renderer.render( this.scene, this.camera, this.depthTarget );
      
      this.scene.overrideMaterial = this.neger;
      this.lava.customOverrideMaterial = this.lavaMaskMat;
      renderer.render(this.scene, this.camera, buffer1);
      this.lava.customOverrideMaterial = null;

      this.scene.overrideMaterial = null;
      this.composer.render();
    },
    controlCamera: function(camera)
    {
      var v7 = getVal('var2');
      var v6 = getVal('var3');

      if(v7 < 0) {
        v7 = 0;
      }
      if(v6 < 0) {
        v6 = 0;
      }

      if (v7 >= 0 && v7 <=100)
      {
        if(v6 > 100) {
          v6 = 100;
        }
        var campos = this.pigSpline.getPointAt(v7/100)
        var lookpos = this.pigSpline.getPointAt(v6/100)

      } else if (v7 > 100)
      {
        lookpos = new THREE.Vector3(0,0,0);
        campos = this.getCamOrbit(deg2rad(v7-100), deg2rad(v6), 95);
      }

      var camVector = new THREE.Vector3(campos.x + getVal('camx'), campos.y + getVal('camy'), campos.z + getVal('camz'));
      var lookVector = new THREE.Vector3(lookpos.x + getVal('cam2x'), lookpos.y + getVal('cam2y'), lookpos.z + getVal('cam2z'));

      camera.position.set(camVector.x, camVector.y, camVector.z);
      camera.lookAt(lookVector);
    }
  };
})();

var scenes = scenes || [];
scenes[Scene.id] = Scene;
