var Tunnel = (function () {

    "use strict";

    var _model,
        _duration = 0,
        _sync,
        _width,
        _height,
        _ctx,
        _preflightCallback;

    var _feed,
        _zLayer;

    var _blackFade,
        _imageFade,
        _lRot,
        _lY;


    var spread;

    var gfx = ["bierkasten", "cubedudes", "grill", "grillball", "grillierung", "puter", "wurstdude", "wurstfeuer"],
        special = ["mds", "tln", "bbnbs", "dd"];

    function preflight(callbackFn, duration, model) {
        _preflightCallback = callbackFn;

        _duration = duration;
        _model = model;

        _sync = _model.sync;
        _width = _model.width();
        _height = _model.height();

        var canvas = document.createElement('canvas');
        canvas.width = _width;
        canvas.height = _height;
        _feed = canvas.getContext('2d');

        initSync();

        _ctx = _model.twoDeeRenderer;
        spread = 190 / 1920 * _ctx.canvas.width;

        _preflightCallback();
    }

    function init() {
        _zLayer = ZLayer();
        _zLayer.setFeedFunction(fillFeed);
        _zLayer.setContext(_ctx);
        _zLayer.setFeed(_feed);

        _model.on("resize", resize);
    }

    function initSync() {
        _blackFade = _sync.getTrack('blackFade');
        _imageFade = _sync.getTrack('imageFade');

        _lRot = _sync.getTrack('LenkradRotation');
        _lY = _sync.getTrack('LenkradHypf');
    }

    function render(sceneTime, floatBeat, frameDelta, row) {

        _ctx.clearRect(0, 0, _width, _height);

        _zLayer.render(row);
        _ctx.drawImage(Meat.vignette, 0, 0, _width, _height);
        _ctx.drawImage(Meat.interieur, 0, 0, _width, _height);
        lenkrad(_lY.getValue(row), _lRot.getValue(row));

        var imgF = _imageFade.getValue(row),
            bF = _blackFade.getValue(row);

        if(imgF > 0) {
            _ctx.globalAlpha = imgF;
            _ctx.drawImage(Meat.dsmLogo, 0, 0, _width,_height);
            _ctx.globalAlpha = 1;
        }

        if(bF > 0) {
            _ctx.fillStyle = "rgba(0,0,0," + bF + ")";
            _ctx.fillRect(0,0,_width,_height);
        }
    }

    function fillFeed(spriteIndex, z, maxZ) {

        var img;

        if(spriteIndex >= 100)
            img = Meat[special[spriteIndex - 100]];
        else
            img = Meat[gfx[spriteIndex]];

        var pos = z / maxZ * 11;
        addSprite(img, pos * spread);
    }

    function addSprite(sprite, x) {

        var MAX_ROTATION = 10;

        var width = sprite.width / 1920 * _feed.canvas.width,
            height = sprite.height / 1080 * _feed.canvas.height,
            canvasMid = _feed.canvas.width / 2;

        var centerDelta = canvasMid - x;
        var angle = (MAX_ROTATION / canvasMid * centerDelta) * Math.PI / 180;

        var scale = (0.5 / canvasMid * Math.abs(centerDelta)) + 1;

        width *= scale;
        height *= scale;

        _feed.clearRect(0,0,_width,_height);

        var y = _feed.canvas.height - height / 2;
        y += (Math.cos(1 / canvasMid * centerDelta) * height / 4) - height / 4;

        _feed.translate(x, y);
        _feed.rotate(angle);
        _feed.drawImage(sprite, -width / 2, -height / 2, width, height);
        _feed.rotate(-angle);
        _feed.translate(-x, -y);
    }

    function lenkrad(yDelta, rot){
        var sprite = Meat.lenkrad;

        var x = 665 / 1920 * _ctx.canvas.width,
            y = 858 / 1080 * _ctx.canvas.height,
            w = sprite.width / 1920 * _ctx.canvas.width,
            h = sprite.height / 1080 * _ctx.canvas.height;

        var angle = rot * Math.PI / 180;
        _ctx.save();
        _ctx.translate(x, y + yDelta);
        _ctx.rotate(angle);
        _ctx.drawImage(sprite, -w / 2, -h / 2, w, h);
        _ctx.rotate(-angle);
        _ctx.translate(-x, -y + yDelta);
        _ctx.restore();
    }

    function onBeat(integerBeat, msTime, majorBeat, minorBeat) {
    }

    function clear() {
        _model.on("resize", function () {
        });
    }

    function resize(width, height) {
        _width = width;
        _height = height;
    }

    return {
        preflight: preflight,
        init: init,
        render: render,
        onBeat: onBeat,
        clear: clear,
        resize: resize
    };
}());