var Hexa = (function () {

    "use strict";

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

    var _hexagon;

    var _p,
        _polygons;

    var _glow,
        _blackFade;

    var POINTS = 18,
        DIAMETER_MIN,
        DIAMETER_JUMP = 11,
        JUMP_DELTA_DISTANCE = 120,
        JUMP_DELTA_MIN_DISTANCE = 14,
        DISKS = 10,
        PALETTE = [
            '#f6eed0',
            '#fefff0',
            '#e7775e',
            '#60676f',
        ];

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

        _duration = duration;
        _model = model;

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

        initSync();

        _ctx = _model.twoDeeRenderer;

        _preflightCallback();
    }

    function init() {
        _model.on("resize", resize);

        if (_ctx.setLineDash)
            _ctx.setLineDash([0]);
        else {
            try {
                _ctx.mozDash = [1];
            } catch (error) {
            }
        }

        _p = [];
        _polygons = [];
        DIAMETER_MIN = 250 / 1920 * _width;

        initSchwurbel();

        _hexagon = new HexaGone();
        _hexagon.setContext(_ctx);

        var canvas = document.createElement('canvas');
        canvas.width = _width;
        canvas.height = _height;
        _pctx = canvas.getContext('2d');
        _polyfield = new Starfield();
        _polyfield.setContext(_pctx);
        _polyfield.setCenter(_width* 6 /*- (_width / 3) / 2*/, _height);
    }

    var _polyfield,
        _pctx;

    function initSync() {
        //_blackFade = _sync.getTrack('blackFade');
        _blackFade = _sync.getTrack('blackFade');
        _glow = _sync.getTrack('glow');
    }

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

        _hexagon.render(0, 0, frameDelta / 1000);

        var texWidth = Meat.texOver.width / 1920 * _width;
        _ctx.drawImage(Meat.texOver, _width - texWidth, 0,texWidth, Meat.texOver.height / 1080 * _height);

        var multi = 120 / 600 * _width,
            msRow = row * 100;

        for (var i = 0; i < _p.length; i++) {
            var p = _p[i];

            plot(Math.cos(msRow / 800 + i * 100) * Math.cos(msRow / 1000) * multi + _width / 2.5,
                Math.sin(msRow / 800 + i * 100) * Math.cos(msRow / 800) * multi + _height / 2,
                p);
        }

        _pctx.clearRect(0, 0, _width, _height);
        _polyfield.render(frameDelta / 500);
        _ctx.drawImage(_pctx.canvas, 0, 0);

        var glow = _glow.getValue(row);

        var bF = _blackFade.getValue(row);

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

        if (glow > 0) {
            var glowScale = 1;

            for (var i = 0; i < 4; i++) {
                glowScale += .01;
                var sW = _width * glowScale,
                    sH = _height * glowScale;
                _ctx.save();
                _ctx.globalCompositeOperation = 'lighter';
                _ctx.globalAlpha = glow;
                _ctx.drawImage(_ctx.canvas, (_width - sW) / 2, (_height - sH) / 2, sW, sH);
                _ctx.restore();
            }
        }
    }

    function initSchwurbel() {

        var add = .72;// / 1920 * _width;
        var cIdx = 0;

        for (var i = 0; i < DISKS; i += add) {

            if (cIdx >= PALETTE.length)
                cIdx = 0;

            var width = (Math.sin(i / 2 - Math.PI / 2) ) * DIAMETER_MIN,
                coords = [],
                rot = 0;

            for (var c = 0; c < POINTS; c++) {
                var r = Random.float() * (360 / POINTS - JUMP_DELTA_DISTANCE) + JUMP_DELTA_MIN_DISTANCE;

                rot += r / 180 * Math.PI;

                var dist = width + Random.float() * DIAMETER_JUMP,
                    x = Math.cos(rot) * dist,
                    y = Math.sin(rot) * dist
                //,col = Math.round(Random.float() * 3);

                coords.push({
                    "x": x,
                    "y": y,
                    "col": cIdx
                });
            }
            cIdx++;

            _p.push(coords);
        }
    }

    function plot(posX, posY, coords) {

        _ctx.beginPath();

        _ctx.moveTo(coords[0].x + posX, coords[0].y + posY);

        for (var i = 0; i < coords.length; i++) {
            _ctx.lineTo(coords[i].x + posX, coords[i].y + posY);
        }

        _ctx.lineTo(posX + coords[0].x, posY + coords[0].y);
        _ctx.fillStyle = PALETTE[coords[0].col];
        _ctx.strokeStyle = "#3b3f43";
        _ctx.lineWidth = 3 / 1920 * _width;
        _ctx.fill();
        _ctx.stroke();
    }

    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
    };
}());