
//nimiavaruus
TDEMO = {
  audioStatus : false,
  
  inited : false,
  user : false,
  started : false,
  
  //beats per minute
  bpm : 72,
  //seconds per beat (beattien välinen aika sekunteina)
  spb : 1/(72/60),
  //how many seconds per bar
  barLength : 4 * (1/(72/60)),
  //kuinka kauan musiikki kestää sekunteissa
  music_duration : 200,
  bars_total : 60,
  
  //ajastus ja parttien vaihto
  timeElapsed : 0,
  currentPart : 0,
  currentTransformation : 0,
  nextTransformation : 1,
  
  width : 0,
  height : 0,
  minx : 0,
  maxx : 0,
  miny : 0,
  maxy : 0,
  
  //some camera parameters
  fov: 55,
  near : 0.2,
  far: 8000,
  aspect : 1,
  
  //TODO: mieti, miten lopetus tehdään!!
  mainloop : function(){
    
    if(!TDEMO.started){
      TDEMO.started = true;
      TDEMO.audio.play();
    }
    
    TDEMO.timeElapsed = TDEMO.audio.currentTime;
    
    var remove = [];
    
    for(var i = 0; i < TDEMO.postProcessingChanges.length; ++i){
      var change = TDEMO.postProcessingChanges[i];
      if(!change.finished && TDEMO.timeElapsed >= change.startTime && TDEMO.timeElapsed <= change.endTime){        
        var t = TDEMO.timeElapsed - change.startTime;
        var s = change.velocity * t;
        change.modify.value = change.startPoint + s;
      }
      else if(TDEMO.timeElapsed >= change.endTime){
        change.finished = true;
        remove.push(i);
      }
    }
    //removing finished changes from the queue
    /*for(var k = 0; k < remove.length; ++k){
      var index = k;
      var removed = TDEMO.postProcessingChanges.splice(k, 1);
    }*/

    //middle of transformation
    if(TDEMO.timeElapsed >= TDEMO.transformations[TDEMO.currentTransformation].startTime &&
      TDEMO.timeElapsed <= TDEMO.transformations[TDEMO.currentTransformation].endTime &&
      !TDEMO.transformations[TDEMO.currentTransformation].finished)
    {  
      if(!TDEMO.transformations[TDEMO.currentTransformation].started){
        if(TDEMO.transformations[TDEMO.currentTransformation].needsEnabling){
          TDEMO.transformations[TDEMO.currentTransformation].effect.enabled = true;
        }
        TDEMO.transformations[TDEMO.currentTransformation].started = true;
        TDEMO.transformations[TDEMO.currentTransformation].to.prepare(TDEMO.timeElapsed);
      }
      
      //Siirtymäefekti
      if(TDEMO.transformations[TDEMO.currentTransformation].modify){
        var t = TDEMO.timeElapsed - TDEMO.transformations[TDEMO.currentTransformation].startTime
        var s = TDEMO.transformations[TDEMO.currentTransformation].velocity * t;
        TDEMO.transformations[TDEMO.currentTransformation].modify.value =
          TDEMO.transformations[TDEMO.currentTransformation].startPoint + s;
      }
        
      //Molepien skenejen rendaus
      TDEMO.transformations[TDEMO.currentTransformation].from.animate(TDEMO.timeElapsed);
      TDEMO.transformations[TDEMO.currentTransformation].from.render(TDEMO.timeElapsed, TDEMO.postRTT);
      if(TDEMO.transformations[TDEMO.currentTransformation].doubleRender){
        TDEMO.transformations[TDEMO.currentTransformation].to.animate(TDEMO.timeElapsed);
        TDEMO.transformations[TDEMO.currentTransformation].to.render(TDEMO.timeElapsed, TDEMO.RTT);
      }
    }//end of transformation
    else if(TDEMO.timeElapsed >= TDEMO.transformations[TDEMO.currentTransformation].endTime)
    {
      if(TDEMO.transformations[TDEMO.currentTransformation].needsEnabling){
        TDEMO.transformations[TDEMO.currentTransformation].effect.enabled = false;
      }
      TDEMO.transformations[TDEMO.currentTransformation].finished = true;
      TDEMO.currentPart = TDEMO.transformations[TDEMO.currentTransformation].to;
      
      if(TDEMO.nextTransformation < TDEMO.transformations.length){
        TDEMO.currentTransformation = TDEMO.nextTransformation;
        ++TDEMO.nextTransformation;
      }
      
      TDEMO.currentPart.animate(TDEMO.timeElapsed);
      TDEMO.currentPart.render(TDEMO.timeElapsed, TDEMO.RTT);
      
    }//in between transformations
    else{
      TDEMO.currentPart.animate(TDEMO.timeElapsed);
      TDEMO.currentPart.render(TDEMO.timeElapsed, TDEMO.RTT);
    }

    TDEMO.composer.render();
    requestAnimationFrame(TDEMO.mainloop);
  }
  
};

//parttien luominen ja alustaminen.
var initParts= function(){
  //Tähän luodaan partit
  TDEMO.parts = {
    Name : new Name(),
    Lines : new Lines(),
    Grid : new Grid(),
    Balls : new Balls(),
    Towers : new Towers(),
  };
  
  //initial rendering
  TDEMO.parts.Name.render(0, TDEMO.RTT);
  TDEMO.parts.Lines.render(0, TDEMO.RTT);
  TDEMO.parts.Grid.render(0, TDEMO.RTT);
  TDEMO.parts.Balls.render(0, TDEMO.RTT);
  TDEMO.parts.Towers.render(0, TDEMO.RTT);
  
  //tyhjää alussa tahti 1
  //alkukohina tahti 2
  //alkusoitto tahdit 2-10
  
  //A-osa tahdit 10-18
  //B-osa tahdit 18-22
  
  //A-osa tahdit 22-30
  //A-osa tahdit 30-38
  
  //B-osa tahdit 38-42
  
  //C-osa tahdit 42-50
  //A-osa tahdit 50-58
  
  //loppukohina tahdit 58-60
  
  //TÄSSÄ PITÄÄ OLLA VÄHINTÄÄN YKSI SIIRTYMÄ!!!
  TDEMO.transformations = [
    //Alkukohina ja soitto
    { 
      from: TDEMO.parts.Name,//THIS PART NEEDS TO BE 10 BARS LONG
      to: TDEMO.parts.Towers,
      startTime: TDEMO.barLength*9,
      endTime: TDEMO.barLength*10,
      started: false,
      finished: false,
      //Mitä efektiä käytetään siirtymään
      effect : TDEMO.swipePass,
      needsEnabling : true,
      doubleRender : true,
      //Mitä uniformia muutetaan
      modify : TDEMO.swipePass.uniforms["angle"],
      //Millä nopeudella muutetaan
      velocity : (0.5+2.0)/(TDEMO.barLength),
      //Mikä oli efektin alkuarvo
      startPoint : -2.0
    },
    
    //A-osa
    {
      from: TDEMO.parts.Towers,//THIS PART NEEDS TO BE 10 BARS LONG
      to: TDEMO.parts.Grid,
      startTime: TDEMO.barLength*16,
      endTime: TDEMO.barLength*18,
      started: false,
      finished: false,
      //Mitä efektiä käytetään siirtymään
      effect : TDEMO.swipePass,
      needsEnabling : true,
      doubleRender : true,
      //Mitä uniformia muutetaan
      modify : TDEMO.swipePass.uniforms["angle"],
      //Millä nopeudella muutetaan
      velocity : (0.5+2.0)/(TDEMO.barLength*2),
      //Mikä oli efektin alkuarvo
      startPoint : -2.0
    },
    //B-osa ja A-osa,
    {
      from: TDEMO.parts.Grid,//THIS PART NEEDS TO BE 14 BARS LONG
      to: TDEMO.parts.Balls,
      startTime: TDEMO.barLength*(30-TDEMO.spb),
      endTime: TDEMO.barLength*30,
      started: false,
      finished: false,
      //Mitä efektiä käytetään siirtymään
      effect : TDEMO.swipePass,
      needsEnabling : true,
      doubleRender : true,
      //Mitä uniformia muutetaan
      modify : TDEMO.swipePass.uniforms["angle"],
      //Millä nopeudella muutetaan
      velocity : (0.5+2.0)/(TDEMO.spb),
      //Mikä oli efektin alkuarvo
      startPoint : -2.0
    },
    
    //A-osa ja B-osa
    {
      from: TDEMO.parts.Balls,//THIS PART NEEDS TO BE 12 BARS + 1 spb LONG
      to: TDEMO.parts.Lines,//THIS PART NEEDS TO BE 18.5 BARS LONG
      startTime: TDEMO.barLength*(42-TDEMO.spb),
      endTime: TDEMO.barLength*42,
      started: false,
      finished: false,
      //Mitä efektiä käytetään siirtymään
      effect : TDEMO.swipePass,
      needsEnabling : true,
      doubleRender : true,
      //Mitä uniformia muutetaan
      modify : TDEMO.swipePass.uniforms["angle"],
      //Millä nopeudella muutetaan
      velocity : (0.5+2.0)/(TDEMO.spb),
      //Mikä oli efektin alkuarvo
      startPoint : -2.0
    },
    //C-osa, A-osa ja loppu
    //THE END
    
    
  ];
  
  TDEMO.postProcessingChanges = [
    {
      name : "brightness",
      startTime : TDEMO.barLength,
      endTime : TDEMO.barLength*2,
      modify : TDEMO.brightnessPass.uniforms[ "brightness" ],
      velocity : (-0.5+3.0)/(TDEMO.barLength),
      startPoint : -3.0,
      finished : false
    },
    {
      name : "brightness",
      startTime : TDEMO.barLength*6,
      endTime : TDEMO.barLength*10,
      modify : TDEMO.brightnessPass.uniforms[ "brightness" ],
      velocity : (-0.1+0.5)/(TDEMO.barLength*4),
      startPoint : -0.5,
      finished : false
    },
    {
      name : "brightness",
      startTime : TDEMO.barLength*36,
      endTime : TDEMO.barLength*42,
      modify : TDEMO.brightnessPass.uniforms[ "brightness" ],
      velocity : (0.4+0.1)/(TDEMO.barLength*6),
      startPoint : -0.1,
      finished : false
    },
    {
      name : "contrast",
      startTime : TDEMO.barLength*49,
      endTime : TDEMO.barLength*51,
      modify : TDEMO.brightnessPass.uniforms[ "contrast" ],
      velocity : (0.1+0.5)/(TDEMO.barLength*2),
      startPoint : -0.5,
      finished : false
    },
    {
      name : "hblur",
      startTime : TDEMO.barLength*50,
      endTime : TDEMO.barLength*54,
      modify : TDEMO.hblur.uniforms[ "h" ],
      velocity : (3.0/TDEMO.width - 1.0/TDEMO.width)/(TDEMO.barLength*4),
      startPoint : 1.0/TDEMO.width,
      finished : false
    },
    {
      name : "vblur",
      startTime : TDEMO.barLength*50,
      endTime : TDEMO.barLength*54,
      modify : TDEMO.vblur.uniforms[ "v" ],
      velocity : (3.0/TDEMO.width - 1.0/TDEMO.width)/(TDEMO.barLength*4),
      startPoint : 1.0/TDEMO.width,
      finished : false
    },
    
    {
      name : "brightness",
      startTime : TDEMO.barLength*58,
      endTime : TDEMO.barLength*59,
      modify : TDEMO.brightnessPass.uniforms[ "brightness" ],
      velocity : (-3.0-0.4)/(TDEMO.barLength),
      startPoint : 0.4,
      finished : false
    },

    {
      name : "contrast",
      startTime : TDEMO.barLength*59.5,
      endTime : TDEMO.barLength*60,
      modify : TDEMO.brightnessPass.uniforms[ "contrast" ],
      velocity : (-0.5-0.1)/(TDEMO.barLength*0.5),
      startPoint : 0.1,
      finished : false
    },
  ]
  
  //MUISTA ALUSTAA CURRENT PART ENSIMMÄISEKSI PARTIKSI!
  TDEMO.currentPart = TDEMO.parts.Name;
  TDEMO.currentPart.prepare(0);
};


//aloitetaan demo, kun kaikki alustustoimenpiteet
//on varmasti suoritettu
var allLoaded = function(){
  if(TDEMO.audioStatus && TDEMO.inited && TDEMO.user){
    TDEMO.mainloop();
  }
};

var audioReady = function(){
  TDEMO.audioStatus = true;
  TDEMO.audio = document.getElementById("audio");
  
  allLoaded();
};

var start = function(){

  var demoEl = document.getElementById("demo");
  
  if(demoEl.requestFullscreen){
    demoEl.requestFullscreen();
  }
  else if(demoEl.mozRequestFullScreen){
    demoEl.mozRequestFullScreen();
  }
  else if (demoEl.webkitRequestFullscreen){
    demoEl.webkitRequestFullscreen();
  }else{
    console.log("fail");
  }

  document.getElementById("start").style.display = "none";
  document.getElementById("demo").style.display = "block";
  
  //Vähän timeouttia tähän, että käyttäjä ehtii painaa
  //allow -nappia fullscreen modeen siirryttäessä ennen demon alkua.
  setTimeout(function(){
    console.log("Let's start!");
    TDEMO.user = true;
    allLoaded();
  }, 5000);
}


//Alustaa three.js:n, partteihin ja renderöintiin liittyvät jutut
var init = function(){
  TDEMO.screenWidth = screen.width;
  TDEMO.screenHeight = screen.height;
  
  TDEMO.height = TDEMO.screenHeight;
  TDEMO.width = TDEMO.screenWidth;
  
  TDEMO.aspect = TDEMO.width/TDEMO.height;
  
  //some commonly used values
  TDEMO.minx = -TDEMO.width/2;
  TDEMO.maxx = TDEMO.width/2;
  TDEMO.miny = -TDEMO.height/2;
  TDEMO.maxy = TDEMO.height/2;
  
  //alustetaan renderer
  TDEMO.renderer = new THREE.WebGLRenderer();
  TDEMO.renderer.setSize(TDEMO.width, TDEMO.height);
  TDEMO.renderer.setClearColor(0xFFFFFF);
  
  TDEMO.renderer.domElement.style.width = TDEMO.screenWidth;
  TDEMO.renderer.domElement.style.height = TDEMO.screenHeight;
  document.getElementById("demo").appendChild(TDEMO.renderer.domElement);
  
  //Few things to support postprocessing
  TDEMO.RTT = new THREE.WebGLRenderTarget(TDEMO.width, TDEMO.height, {
    minFilter: THREE.LinearFilter,
    magFilter: THREE.NearestFilter,
    format: THREE.RGBFormat
  });
  
  TDEMO.postRTT = new THREE.WebGLRenderTarget(TDEMO.width, TDEMO.height, {
    minFilter: THREE.LinearFilter,
    magFilter: THREE.NearestFilter,
    format: THREE.RGBFormat
  });
  
  TDEMO.scene = new THREE.Scene();
	TDEMO.camera = new THREE.OrthographicCamera(TDEMO.minx, TDEMO.maxx, TDEMO.maxy, TDEMO.miny);
	TDEMO.camera.position.z = 1;
	TDEMO.scene.add(TDEMO.camera);
  
  var display = new THREE.Mesh(new THREE.PlaneGeometry(TDEMO.width, TDEMO.height),
    new THREE.MeshBasicMaterial({map : TDEMO.RTT}));
	display.position.z = -1;
  TDEMO.scene.add(display);
  
  //POSTPROCESSING PIPELINE
  
  //COMPOSER
  TDEMO.composer = new THREE.EffectComposer(TDEMO.renderer);
  TDEMO.renderPass = new THREE.RenderPass(TDEMO.scene, TDEMO.camera);
  TDEMO.composer.addPass(TDEMO.renderPass);
  
  //TRANSFORMATION PASS, NOT ENABLED BY DEFAULT
  TDEMO.swipePass = new THREE.ShaderPass(SwipeShader);
  TDEMO.swipePass.uniforms[ "scene1" ].value = TDEMO.postRTT;
  TDEMO.swipePass.uniforms[ "scene2" ].value = TDEMO.RTT;
  TDEMO.swipePass.uniforms[ "resolution" ].value = new THREE.Vector2(TDEMO.width, TDEMO.height);
  TDEMO.composer.addPass(TDEMO.swipePass);
  TDEMO.swipePass.enabled = false;

  //THE VISUAL PIPELINE WHICH IS APPLIED TO ALL BY DEFAULT
  TDEMO.brightnessPass = new THREE.ShaderPass(THREE.BrightnessContrastShader);
  TDEMO.brightnessPass.uniforms[ "brightness" ].value = -3.0;
  TDEMO.brightnessPass.uniforms[ "contrast" ].value = -0.5;
  TDEMO.composer.addPass(TDEMO.brightnessPass);
  
  TDEMO.hblur = new THREE.ShaderPass( THREE.HorizontalBlurShader );
  TDEMO.hblur.uniforms[ "h" ].value =  1.0/TDEMO.width;
  TDEMO.composer.addPass(TDEMO.hblur);
  
  TDEMO.vblur = new THREE.ShaderPass( THREE.VerticalBlurShader );
  TDEMO.vblur.uniforms[ "v" ].value = 1.0/TDEMO.height;
  TDEMO.composer.addPass(TDEMO.vblur);
  
  //THE LAST THING TO COMBINE ALL
  TDEMO.copyPass = new THREE.ShaderPass(THREE.CopyShader);
  TDEMO.copyPass.renderToScreen = true;
  TDEMO.composer.addPass(TDEMO.copyPass);

  initParts();
  
  //alustus on tehty, kutsutaan tarkastusfunktiota
  TDEMO.inited = true;
  allLoaded();
};


