
const settings = new Settings();
settings.engine.preload = true;

settings.demo.renderer.sortObjects = true;
settings.demo.renderer.logarithmicDepthBuffer = false;
settings.demo.sync.rocketFile = 'sync/demo.rocket';
settings.demo.sync.beatsPerMinute = 135;
settings.demo.sync.rowsPerBeat = 8;
settings.demo.camera.near = 0.1;
settings.demo.camera.far = 1000.0;
settings.demo.duration = 60000;
settings.demo.music.loop = false;
//settings.demo.clearColor = { r: 1.0, g: 1.0, b: 1.0, a: 1.0 };
settings.demo.model.shape.material.type = 'Standard';
settings.demo.shadow.mapSize.width = 2048;
settings.demo.shadow.mapSize.height = settings.demo.shadow.mapSize.width;
settings.demo.image.texture.minFilter = 'NearestFilter';
settings.demo.image.texture.magFilter = 'NearestFilter';
//settings.demo.image.texture.wrapS = 'RepeatWrapping';
//settings.demo.image.texture.wrapT = 'RepeatWrapping';
settings.demo.fbo.color.texture.minFilter = 'NearestFilter';
settings.demo.fbo.color.texture.magFilter = 'NearestFilter';
//settings.demo.fbo.color.texture.wrapS = 'RepeatWrapping';
//settings.demo.fbo.color.texture.wrapT = 'RepeatWrapping';
settings.engine.fps = 60;

const deg2rad = 0.01745329251;
window.camPos = [0.0, 0.0, 0.0];
window.camPosLength = 1.0;
window.camFov = 0.0;
window.beat = 60 / 100;
window.tick = window.beat / 8;
window.pattern = window.beat * 6;
window.camNear = 0.0;
window.camFar = 0.0;
window.globalTime = 0.0;

window.endpattern = (60 / 145) * 8;
includeFile('multiSceneEffects/PostProcess.js');
includeFile('multiSceneEffects/dof.js');
includeFile('scenes/intro/intro.js');
includeFile('multiSceneEffects/shaderInjections.js');

Demo.prototype.cameraSetup = function (stopCamAt) {
    this.loader.addAnimation({
        "camera": "cam1"
        , "position": [{ "x": 0, "y": 0, "z": 10 }]
        , "lookAt": [{ "x": 0.0, "y": 0.0, "z": 0.0 }]
        , "up": [{ "x": 0, "y": 1, "z": 0 }]
        , "perspective": [{ "fov": 75, "aspect": 16 / 9, "near": .05, "far": 1000 }]
        , "distYawPitch": [-5.0, 1, 2.0]
        , "instableTimer": [0.0, 0.0, 0.0, 0.0, 0.0]
        , "runPreFunction": (animation) => {
            for (let i = 0; i < animation.instableTimer.length; i++) {
                animation.instableTimer[i] += Math.random() * getDeltaTime();
            }
            let distance = .05 * Sync.get('Cam:Instability') * Math.sin(1.8 * animation.instableTimer[3]) + Sync.get('Cam:Distance');
            let pitch = (Sync.get('Cam:Instability') * 5 * Math.cos(2.4 * animation.instableTimer[1]) + Sync.get('Cam:Yaw')) * deg2rad;
            let roll = (Sync.get('Cam:Instability') * 5 * Math.sin(3.1 * animation.instableTimer[2]) + Sync.get('Cam:Pitch')) * deg2rad;
            let yaw = 0.0;
            let target = [Sync.get('Cam:TargetX'), Sync.get('Cam:TargetY'), Sync.get('Cam:TargetZ')];
            let points = [0, 0, distance];
            let cosa = Math.cos(yaw),
                sina = Math.sin(yaw);
            let cosb = Math.cos(pitch),
                sinb = Math.sin(pitch);
            let cosc = Math.cos(roll),
                sinc = Math.sin(roll);
            let Axx = cosa * cosb,
                Axy = cosa * sinb * sinc - sina * cosc,
                Axz = cosa * sinb * cosc + sina * sinc;
            let Ayx = sina * cosb,
                Ayy = sina * sinb * sinc + cosa * cosc,
                Ayz = sina * sinb * cosc - cosa * sinc;
            let Azx = -sinb,
                Azy = cosb * sinc,
                Azz = cosb * cosc;
            let px = points[0];
            let py = points[1];
            let pz = points[2];
            let newPoints = [
                (Axx * px + Axy * py + Axz * pz) + target[0],
                Ayx * px + Ayy * py + Ayz * pz + target[1],
                Azx * px + Azy * py + Azz * pz + target[2]
            ];
            window.camPos = newPoints;
            window.camPosLength = Math.sqrt(newPoints[0] * newPoints[0] + newPoints[1] * newPoints[1] + newPoints[2] * newPoints[2]);
            animation.position[0].x = newPoints[0];
            animation.position[0].y = newPoints[1];
            animation.position[0].z = newPoints[2];
            animation.lookAt[0].x = Sync.get('Cam:Instability') * .25 * Math.sin(2 * animation.instableTimer[3]) + Sync.get('Cam:TargetX');
            animation.lookAt[0].y = Sync.get('Cam:Instability') * .25 * Math.cos(2 * animation.instableTimer[4]) + Sync.get('Cam:TargetY');
            animation.lookAt[0].z = Sync.get('Cam:TargetZ');
            animation.perspective[0].fov = Sync.get('Cam:FOV');
            window.camNear = animation.perspective[0].near;
            window.camFar = animation.perspective[0].far;
            window.camFov = animation.perspective[0].fov * deg2rad;

            let camRoll = Sync.get('Cam:Roll') * deg2rad;
            animation.up[0].x = -Math.sin(camRoll);
            animation.up[0].y = Math.cos(camRoll);
            animation.up[0].z = 0;

        }
    });


};

Demo.prototype.setScene = function (sceneName) {
    this.loader.setScene(sceneName);
    this.cameraSetup();
};

Demo.prototype.init = function () {
    const bpm = settings.demo.sync.beatsPerMinute;
    const beat = 60 / bpm;

    this.sceneIntro();


    this.loader.setScene('main');

    const scenes = [
        // intro
        { start: 0, duration: 99999999, name: 'intro', dof: true, prePostProcessing: false },
    ];

    scenes.forEach((scene) => {
        this.loader.addAnimation({ start: scene.start, duration: scene.duration, scene: { name: scene.name, fbo: { name: scene.name + 'Fbo' } }, ...(scene.parameters || {}) });
    });


    this.loader.addAnimation({ fbo: { name: 'screenDof', action: 'begin', storeDepth: false } });
    scenes.forEach((scene) => {
        if (scene.dof) {
            this.loader.addAnimation({
                start: scene.start, duration: scene.duration, color: scene.color, image: [scene.name + 'Fbo.depth.fbo', scene.name + 'Fbo.color.fbo'],
                material: { blending: 'CustomBlending', blendEquation: 'MaxEquation', blendSrc: 'SrcColorFactor', blendDst: 'SrcColorFactor' },
                shader: { name: 'multiSceneEffects/depthToColor.fs' }
            });
        }
    });



    this.loader.addAnimation({ fbo: { name: 'screenDof', action: 'unbind' } });

    this.loader.addAnimation({ fbo: { name: 'screenFbo', action: 'begin', storeDepth: false } });
    scenes.forEach((scene) => {
        if (scene.dof) {
            this.loader.addAnimation({ start: scene.start, duration: scene.duration, color: scene.color, image: scene.name + 'Fbo.color.fbo', additive: scene.additive ?? false });
        }
    });
    this.loader.addAnimation({ fbo: { name: 'screenFbo', action: 'unbind' } });

    this.loader.addAnimation({ fbo: { name: 'blur', action: 'begin', storeDepth: false } });
    this.loader.addAnimation({
        image: 'screenFbo.color.fbo',
        shader: {
            name: 'multiSceneEffects/gaussianBlur.fs',
            variable: [
                { "name": "directions", "value": [16.0] },
                { "name": "quality", "value": [4.0] }, // 4
                { "name": "size", "value": [16.0] } // 16
            ]
        }
    });
    this.loader.addAnimation({ fbo: { name: 'blur', action: 'unbind' } });

    this.loader.addAnimation({ fbo: { name: 'postProcessableFbo', action: 'begin', storeDepth: false } });
    this.loader.addAnimation({
        image: ['screenFbo.color.fbo', 'blur.color.fbo', 'screenDof.color.fbo'],
        shader: {
            name: 'multiSceneEffects/dof.fs',
            variable: [
                { "name": "dofCenter", "value": [() => Sync.get('General:dofCenter')] },
                { "name": "dofWidth", "value": [() => Sync.get('General:dofWidth')] }
            ]
        }
    });



    scenes.forEach((scene) => {
        if (!scene.dof) {
            this.loader.addAnimation({ start: scene.start, duration: scene.duration, color: scene.color, image: scene.name + 'Fbo.color.fbo', additive: scene.additive ?? false });
        }
    });


    this.loader.addAnimation({ fbo: { name: 'postProcessableFbo', action: 'unbind' } });

    this.addPostProcess('postProcessableFbo.color.fbo');
    /*
      this.loader.addAnimation({
        image: 'screenDof.color.fbo'
      });
    */

    this.loader.addAnimation({
        image: '_embedded/defaultTransparent.png',
        shader: {
            name: 'multiSceneEffects/vignette.fs',
            variable: [
                { "name": "vignetteStrength", "value": [() => Sync.get('PostProc:VignetteStrength')] }
            ]
        }
    });



    this.loader.addAnimation({
        image: ['img/demoshop.png'],
        visible:()=>Sync.get('Objects:ScrollTextVisible') > 0.05,    
        perspective: '2d',
        scale: [{ uniform2d: () => Math.sin(getSceneTimeFromStart() * 3) * .025 + Sync.get('DemoShop:Scale') }],
        textureProperties: [{ wrapS: 'RepeatWrapping', wrapT: 'RepeatWrapping' }],
        position: [{ y: () => Sync.get('DemoShop:y'), x: () => Sync.get('DemoShop:x') }],

        color: [{ r: 0.8, g: 0.8, b: 0.8 }]
    });

    // song list

    this.loader.addAnimation({
        image: ['img/songlist.png'],
        perspective: '2d',
        visible: () => Sync.get('Objects:SongListVisible') > 0.05,
        scale: [{ uniform2d: () => Math.sin(getSceneTimeFromStart() * 2) * .005 + .8 }],
        position: [{ x: 0, y: () => Sync.get('Objects:Songlist') }],

    });

    // ekat tekstit

    this.loader.addAnimation({
        image: ['img/aitext.png'],
        perspective: '2d',
        visible: () => Sync.get('Objects:AiTextVisible') > 0.05,
        scale: [{ uniform2d: 1.25 }],
        position: [{ y: 0.35, x: 0 }],

    });

    this.loader.addAnimation({
        image: ['img/newdreamstext.png'],
        perspective: '2d',
        visible: () => Sync.get('Objects:NewDreamsTextVisible') > 0.05,
        scale: [{ uniform2d: 1.25 }],
        position: [{ y: 0.35, x: 0 }],

    });

    // order now

    this.loader.addAnimation({
        image: ['img/ordernow.png'],
        perspective: '2d',
        visible: () => Sync.get('Objects:endtext') > 0.05,
        scale: [{ uniform2d: ()=>.9 +Math.sin(getSceneTimeFromStart()*2)*.05 }],
        position: [{ y: 0.37, x: 0 }],

    });

    this.loader.addAnimation({
        image: ['img/www.png'],
        perspective: '2d',
        visible: () => Sync.get('Objects:endtext') > 0.05 && Math.sin(getSceneTimeFromStart() * 16) > 0,
        scale: [{ uniform2d: .9 }],
        position: [{ y: -0.25, x: 0 }],

    });
    // logot

    this.loader.addAnimation({
        image: ['img/ai_logo.png'],
        perspective: '2d',
        visible: () => Sync.get('Objects:AiLogoVisible') > 0.05,
        scale: [{ uniform2d: 15.0 }],
        position: [{ x: 0, y:0 }],
        color: [{ a: ()=>Sync.get('Objects:AiLogoAlpha') }],

    });
    this.loader.addAnimation({
        image: ['img/ai_logo_nobg.png'],
        perspective: '2d',
        visible: () => Sync.get('Objects:AiLogoVisible') > 0.05,
        scale: [{ uniform2d: 1.0 }],
        position: [{ x: 0, y: () => Sync.get('Objects:ailogo') }],

    });

    //cd:t

    this.loader.addAnimation({
        image: ['img/text_5music.png'],
        perspective: '2d',
        visible: () => Sync.get('Objects:CubeScale') > 0.05,
        scale: [{ uniform2d: () => Math.sin(getSceneTimeFromStart() * 2) * .02 + .8 }],
        position: [{ y: .37, x: 0 }],

    });

    for (let i = 0; i < 5; i++) {
        this.loader.addAnimation([{
            visible: () => Sync.get('Objects:CubeScale') > 0.05,
            object: {
                name: "obj/cd.obj",
            }
            , position: [{
                y: () => Utils.interpolateLinear(Math.max(Math.min(Sync.get('Overlay:CDPos') - i * .5, 1.0), 0.0), 0.0, i % 2 === 0 ? -.4 : .7),
                x: () => Utils.interpolateLinear(Math.max(Math.min(Sync.get('Overlay:CDPos') - i * .5, 1.0), 0.0), 0.0, i - 1.9),
                z: -2
            }],
            angle: [{
                degreesX: () => (i * 33 + getSceneTimeFromStart()) * 70,
                degreesY: () => (i * 33 + getSceneTimeFromStart()) * 80,
                degreesZ: () => (i * 33 + getSceneTimeFromStart()) * 90,
            }],
            scale: [{ uniform3d: () => Math.min(Utils.interpolateLinear(Math.max(Sync.get('Overlay:CDPos') - i * .5, 0.0), 0.0, 1.65), 1.65) }],
            color: [{ a: .75 }],
            material: {
                blending: 'NormalBlending',
                transparent: true,
                depthWrite: false,
                depthTest: false
            }
     
        }]);
    }
    this.loader.addAnimation({
        image: ['img/satisfaction.png'],
        perspective: '2d',
        visible: () => Sync.get('Objects:SatisfactionVisible') > 0.05,
        scale: [{ uniform2d: 1.25 }],
        color: [{ r: 1, g: 1, b: 1 }],
        position: [{ y: -.29, x: ()=>Math.sin(getSceneTimeFromStart()*3)*.05 }],

    });
    this.loader.addAnimation({
        shape: {
            type: 'PLANE',
            width: 2,
            height: 2,
            widthSegments: 2,
            heightSegments: 2
        },
        visible:()=>Sync.get('Objects:ScrollTextVisible') > 0.05,
        perspective: '2d',
        scale: [{ x: 40, y: 3 }],
        color: [{ r: 1, g: 1, b: 1, a: 1 }],

        position: [{
            x: 0,
            y: -7.2,
            z: -5
        }],
        material: {

            transparent: false,
            depthWrite: false,
            depthTest: false
        }
    });
    let scrollText = `New deal from Jumalauta DemoShop is here! Brand new, straight from the press Acid Idiot EP, 'New Dreams For You', is available now! Visit www.AcidIdiot.com for more information! Regular price "Pay What You Want", but Jumalauta DemoShop customers get an extra 20% discount with code "jumalauta"! Remember to visit www.AcidIdiot.com! All tracks 135bpm - 25% more stable than competitor tracks! Visit www.AcidIdiot.com for more information! Contains four tracks, but if you order NOW you'll get an extra track FREE OF CHARGE! Visit www.AcidIdiot.com for more information! Order NOW from www.AcidIdiot.com and remember to use code "jumalauta"! Visit www.AcidIdiot.com for more information!`;

    this.loader.addAnimation([{
        text: { string: scrollText, name: "multiSceneEffects/VT323-Regular.ttf" },
        perspective: "2d",
        color: [{ "r": 255, "g": 1, "b": 1 }],
        position: [{ x: scrollText.length * .0365, y: -1.8 }],
        scale: [{ x: 10, y: 10, z: 1 }],
        visible:()=>Sync.get('Objects:ScrollTextVisible') > 0.05,
        shader: {
            vertexShaderPrefix: `
              uniform float lenght;
              uniform float xpos;
            `,
            vertexShaderSuffix: `

              vec3 pos = position;
              float size = 0.2;
              pos.y = pos.y;
              pos.x = pos.x-xpos*20.;
              pos.z = pos.z;
              gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
            `,
            variable: [
                { name: 'lenght', value: [scrollText.length * .5] },
                { name: 'xpos', value: [() => .3 * getSceneTimeFromStart()] }
            ],
            additive: true,
            material: {
                blending: 'AdditiveBlending',
                transparent: false,
                depthWrite: false,
                depthTest: false
            }
        }
    }]);

    this.loader.addAnimation({
        image: ['img/scanz.png'],
        perspective: '2d',
        color: [{ r: .15, g: .15, b: .15, a: 1 }],
        scale: [{ uniform2d: 1 }],
        material: {
            blending: 'SubtractiveBlending',
        },

    });

};

