(function($){
    $.snowfall = function(element, options){
        var	defaults = {
            flakeCount : 35,
            flakeColor : '#ffffff',
            flakeIndex: 999999,
            minSize : 1,
            maxSize : 3,
            minSpeed : 2,
            maxSpeed : 3
        },
        options = $.extend(defaults, options),
        random = function random(min, max){
            return Math.round(min + Math.random()*(max-min));
        };
			
        $(element).data("snowfall", this);
			
        function Flake(_x, _y, _size, _speed, _id)
        {
            this.id = _id;
            this.x  = _x;
            this.y  = _y;
            this.size = _size;
            this.speed = _speed;
            this.step = 0,
            this.stepSize = random(1,10) / 100;
				
            var flakeMarkup = $(document.createElement("div")).html("*").attr({
                'class': 'snowfall-flakes',
                'id' : 'flake-' + this.id
                }).css({
                'width' : this.size,
                'height' : this.size,
                'color' : options.flakeColor,
                'position' : 'absolute',
                'top' : this.y,
                'left' : this.x,
                'fontSize' : this.size,
                'zIndex' : options.flakeIndex
                });
				
            if($(element).get(0).tagName === $(document).get(0).tagName){
                $('body').append(flakeMarkup);
                element = $('body');
            }else{
                $(element).append(flakeMarkup);
            }
				
            this.element = document.getElementById('flake-' + this.id);

            this.update = function(){
                this.y += this.speed;
					
                if(this.y > (elHeight) - 6){
                    this.reset();
                }
					
                this.element.style.top = this.y + 'px';
                this.element.style.left = this.x + 'px';
					
                this.step += this.stepSize;
                this.x += Math.cos(this.step);
					
                if(this.x > (elWidth) - 6 || this.x < 6){
                    this.reset();
                }
            }

            this.reset = function(){
                this.y = 0;
                this.x = random(0, elWidth);
                this.stepSize = random(1,10) / 100;
                this.size = random((options.minSize * 100), (options.maxSize * 100)) / 100;
                this.speed = random(options.minSpeed, options.maxSpeed);
            }
        }

        var flakes = [],
        flakeId = 0,
        i = 0,
        elHeight = $(element).height() - options.maxSize,
        elWidth = $(element).width() - options.maxSize;

        $(window).bind("resize", function(){
            elHeight = $(element).height() - options.maxSize;
            elWidth = $(element).width() - options.maxSize;
        });
			
        for(i = 0; i < options.flakeCount; i+=1){
            flakeId = flakes.length;
            flakes.push(new Flake(random(0,elWidth), random(0, elHeight), random((options.minSize * 100), (options.maxSize * 100)) / 100, random(options.minSpeed, options.maxSpeed), flakeId));
        }

        function snow(){
            for( i = 0; i < flakes.length; i += 1){
                flakes[i].update();
            }
				
            setTimeout(function(){
                snow()
                }, 30);
        }
			
        snow();

        this.clear = function(){
            $(element).children('.snowfall-flakes').remove();
            flakes = [];
        };
    };
	
    $.fn.snowfall = function(options){
        if(typeof(options) == "object" || options == undefined){
            return this.each(function(i){
                (new $.snowfall(this, options));
            });
        }else if (typeof(options) == "string") {
            return this.each(function(i){
                var snow = $(this).data('snowfall');
                if(snow){
                    snow.clear();
                }
            });
        }
    };
})(jQuery);
