var Main = function(){

    var conf = TDEMO.SYNC.getConfig();
    var syncDevice = TDEMO.SYNC.getSyncDevice();

    var audio = false;

    //Initializing renderer
    var renderer = new THREE.WebGLRenderer();
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setClearColor(0x000000);
    renderer.autoClear = false;

    //RENDERING PIPELINE
    var composer = new THREE.EffectComposer(renderer);

    var fades = new THREE.ShaderPass(THREE.ParaguayFades);
    fades.uniforms[ "brightness" ].value = 0.0;
    fades.uniforms[ "fade" ].value = 1.0;
    fades.uniforms[ "fadeColor" ].value =new THREE.Vector3(0.0, 0.0, 0.0);

    var filmPass = new THREE.FilmPass(0.5, 0.05, 4096, 0);
    var glitchPass = new THREE.GlitchPass();

    var colorcorrect = new THREE.ShaderPass(THREE.ParaguayColorCorrect);
    //calibrate this according to screen!
    colorcorrect.uniforms[ "gamma" ].value = new THREE.Vector3(2.2, 2.2, 2.2);

    var copyPass = new THREE.ShaderPass(THREE.CopyShader);
    copyPass.renderToScreen = true;

    composer.addPass(fades);
    composer.addPass(glitchPass);
    composer.addPass(filmPass);
    composer.addPass(colorcorrect);
    composer.addPass(copyPass);

    var parts = [];
    var partIndex = false;
    var mainPart = false;

    var started = false;
    var timeElapsed = 0;
    var clock = new THREE.Clock();

    //The main loop!
    var mainloop = function(){
        if(!started){
            started = true;
            audio = document.getElementById("audio");
            mainPart.prepare(0);

            if(conf.isDemoMode()) {
                audio.play();
            }
            else{
                audio.pause();
                audio.currentTime = conf.getRow()/conf.getRowRate();
            }
        }

        timeElapsed = audio.currentTime;
        if(!audio.paused) {
            //otherwise we may jump into a point in the audio where there's
            //no timeframe, resulting in Rocket setting row 2 and we report
            //row 1 back - thus Rocket spasming out
            conf.setRow(timeElapsed * conf.getRowRate());
            // this informs Rocket where we are
            syncDevice.update(conf.getRow());
        }

        var bright = TDEMO.SYNC.getBrightness();
        fades.uniforms[ "brightness" ].value = bright;

        var fade = TDEMO.SYNC.getFadeValue();
        fades.uniforms[ "fade" ].value = fade;

        var fadeColor = TDEMO.SYNC.getFadeColor();
        fades.uniforms[ "fadeColor" ].value = fadeColor;

        var negate = TDEMO.SYNC.getNegate();
        fades.uniforms[ "negate" ].value = negate;

        var glitch = TDEMO.SYNC.getGlitch();
        if(glitch > 0){
            glitchPass.goWild = true;
        }
        else{
           glitchPass.goWild = false;
        }

        filmPass.enabled = TDEMO.SYNC.getFilmPassEnabled();

        var grayscale = TDEMO.SYNC.getGrayscale();
        filmPass.uniforms["grayscale"].value = grayscale;

        var index = TDEMO.SYNC.getPart();
        if(index !== partIndex && index < parts.length && index >= 0){
            partIndex = index;
            mainPart.finish();
            mainPart = parts[partIndex];
            mainPart.prepare(timeElapsed);
        }

        var delta = clock.getDelta();
        mainPart.animate(timeElapsed, delta);

        //renderer.clear();
        composer.render(delta);

        if(conf.isDemoMode() || !audio.paused){
            if(audio.ended && conf.isDemoMode()){
                cancelAnimationFrame(mainloop);
            }
            else{
                requestAnimationFrame(mainloop);
            }
        }
        else{
            cancelAnimationFrame(mainloop);
        }
    };

    //Public interface
    var state = {

        setRendererSize : function(width, height){
            renderer.setSize(width, height);
            composer.setSize(width, height);

            renderer.domElement.style.width = width;
            renderer.domElement.style.height = height;

            document.getElementById("demo").appendChild(renderer.domElement);
        },

        getRendererSize : function(){
            return [renderer.domElement.width, renderer.domElement.height];
        },

        setParts : function(p){
            parts = p;
            mainPart = parts[0];
            partIndex = 0;
        },

        getRenderer : function(){
            return renderer;
        },

        getComposer : function(){
            return composer;
        },

        disableCopyPass : function(){
            copyPass.enabled = false;
        },

        enableCopyPass : function(){
            copyPass.enabled = true;
        },

        mainloop : mainloop
    };
    return state;
};

TDEMO.MAIN = Main();
