Taggr = function Taggr(){

    var canvas, gfx;

    // b-spline drawing with bezier curves
    function _drawBSpline(vertices){
        var nv = vertices.length;
        if(nv >= 4){
            var p0 = vertices[0], p1, p2;
            gfx.beginPath();
            gfx.moveTo(p0.x, p0.y);
            for(var i = 1, n = nv-1; i <= n; i++){
                p0 = vertices[i - 1];
                p1 = vertices[i];
                if(i == n){  // finish him
                    gfx.bezierCurveTo(
                        (2*p0.x + p1.x) / 3, (2*p0.y + p1.y) / 3,
                        (2*p1.x + p0.x) / 3, (2*p1.y + p0.y) / 3,
                        p1.x, p1.y
                    );
                }
                else{
                    p2 = vertices[i + 1];
                    gfx.bezierCurveTo(
                        (2*p0.x + p1.x) / 3, (2*p0.y + p1.y) / 3,
                        (2*p1.x + p0.x) / 3, (2*p1.y + p0.y) / 3,
                        (p0.x + 4*p1.x + p2.x) / 6, (p0.y + 4*p1.y + p2.y) / 6
                    );
                }
            }
            gfx.stroke();
            gfx.closePath();
        }
    }

    // 9-cel drawing
    var tile_offs = [
        {x:-1, y:-1}, {x: 0, y:-1}, {x: 1, y:-1},
        {x:-1, y: 0}, {x: 0, y: 0}, {x: 1, y: 0},
        {x:-1, y: 1}, {x: 0, y: 1}, {x: 1, y: 1}
    ];
    function _drawTiled(func){
        var w = canvas.width;
        var h = canvas.height;
        for(var o = 0; o < 9; o++){
            gfx.save();
            gfx.translate(tile_offs[o].x * w, tile_offs[o].y * h);
            func();
            gfx.restore();
        }
    }


    function _rand2(min, max){
        return min + Math.random() * (max - min);
    }
    function _randInt2(min, max){  // min-max inclusive
        return Math.round(min + Math.random() * (max - min));
    }
    
    function _dist(p1, p2){
        var xo = p2.x - p1.x,
            yo = p2.y - p1.y;
        return Math.sqrt(xo * xo + yo * yo);
    }


    function _drawRiceBG(){
        for(var t = _randInt2(5, 10); --t >= 0;){
            var xo = _rand2(0, canvas.width),
                yo = _rand2(0, canvas.height),
                mv  = _rand2(10, 30),
                rnd = _rand2(20, 80),
                vertices = [];
            for(var i = _randInt2(4, 7); --i >= 0;){
                vertices.push({
                    x: (xo += mv + _rand2(-rnd, rnd)),
                    y: (yo -= mv + _rand2(-rnd, rnd))
                });
            }
            gfx.strokeStyle = '#bbbbbb';
            gfx.lineWidth = '2';
            gfx.lineCap = 'round';
            _drawTiled(function(){
                _drawBSpline(vertices);
            });
        }
    }
    
    function _drawPlusBG(){
        var plusses = [], plus, i;
        for(var t = _randInt2(5, 10); --t >= 0;){
            plus = {
                pos: {
                    x: _rand2(0, canvas.width),
                    y: _rand2(0, canvas.height)
                },
                rot:   _rand2(0, Math.PI),
                scale: _rand2(20, 40)
            };
            for(i = plusses.length; --i >= 0;){
                if(_dist(plus.pos, plusses[i].pos) < plus.scale + plusses[i].scale)
                    break;
            }
            if(i == -1){
                plusses.push(plus);
                _drawTiled(function(){
                    gfx.save();
                    gfx.translate(plus.pos.x, plus.pos.y);
                    gfx.rotate(plus.rot);
                    gfx.scale(plus.scale / 3, plus.scale / 3);
                    gfx.fillStyle = '#1b61ff';
                    gfx.fillRect(-1, -3, 2, 2);
                    gfx.fillRect( 1, -1, 2, 2);
                    gfx.fillRect(-1,  1, 2, 2);
                    gfx.fillRect(-3, -1, 2, 2);
                    gfx.fillStyle = '#ffff00';
                    gfx.fillRect(-1, -1, 2, 2);
                    gfx.restore();
                });
            }
        }
    }


    function _createCanvas(width, height){
        canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;
        canvas.style.display = 'none';
        gfx = canvas.getContext('2d');
    }

    function _applyBackground(){
        document.body.style.backgroundImage = 'url(' + canvas.toDataURL('image/png') + ')';
    }

    return {
        generateBackground: function(width, height){
            _createCanvas(width, height);
            switch((new Date()).getDate() % 2){
                case 0:
                    _drawRiceBG(); break;
                case 1:
                    _drawPlusBG(); break;
            }
            _applyBackground();
        }
    };

}();