/**
 * X-Team Snow
 * @author Andrew Valums
 *
 * Copyright (c) 2009 X-Team, http://x-team.com
 */
(function(){
    /**
     * Attaches event to a dom element
     */
    function addEvent(el, type, fn){
    	if (el.addEventListener){
    		el.addEventListener(type, fn, false);
    	} else if (el.attachEvent){
    		el.attachEvent('on' + type, fn)
    	}
    }
    /**
     * Attaches function to window load event in correct
     * order (ie6/7/8 attachEvent adds it in random)
     */
    function addLoadEvent(fn){        
        if (typeof window.onload != 'function'){
            window.onload = fn;
        } else {
            var old = window.onload;
	        window.onload = function() {
                old();
                fn();
            }
        }
    }    
    /**
     * Get scroll value of a window 
     */
    function getScroll(){
        var res = {};
        
        for (type in {'Top':'', 'Left':''}){
            var coord = (type == 'Top') ? 'Y' : 'X';
              
            if(typeof window['page' + coord + 'Offset'] != 'undefined'){
                res[type.toLowerCase()] = window['page' + coord + 'Offset'];                
            } else {
                var obj;
                if ( document.documentElement.clientHeight){
                    obj = document.documentElement;
                } else {
                    obj = document.body;
                }
                res[type.toLowerCase()] = obj['scroll' + type];
            }           
        }        
                
        return res;
    }
    
    function getInnerHeight(){
        var body = document.body,
            height;        
        if (window.innerHeight){
            height = window.innerHeight;
        } else if (body.parentElement.clientHeight) {
            height = body.parentElement.clientHeight;
        } else if (body && body.clientHeight) {
            height = body.clientHeight;
        }
        return height;
    }


            
    // is window loaded?
    var windowLoaded = false;    
    addLoadEvent(function(){
        windowLoaded = true;
    });
    
    // set to false to remove snow
    var enabled = true;           
    
    /**
     * Adds animating snowflakes
     * This function takes 2 arguments
     * First is the path to the directory with snowflake images
     * Second is the maximum number of snowflakes, please do not
     * set this number above 60 as it will impact the performance
     */    
    window.createSnow = function(path, max){
        if ( ! windowLoaded){
            addLoadEvent(function(){
                createSnow(path, max);
            });
            return;            
        }
        
        /**
        * Array with flakes objects
        */
        var flakes = [];
                               
        var interval = setInterval(function(){                      
            if (enabled && max > flakes.length && Math.random() < max * 0.0025){
                flakes.push(new Flake(path)); 
            }
            
            if (!enabled && !flakes.length){
                clearInterval(interval);
            }
            
            
            var scrollTop = getScroll().top,
                innerHeight = getInnerHeight();
            
            for (var i = flakes.length-1; i >= 0; i--){
                if ( ! flakes[i]){
                    continue;
                }              
                
                if (flakes[i].top < scrollTop || flakes[i].top + flakes[i].size + 1 > scrollTop + innerHeight){
                    flakes[i].remove();
                    flakes[i] = null;
                    flakes.splice(i,1);
                    continue;
                }
                
                flakes[i].move();
                flakes[i].draw();
            }
                            
        }, 40);
        
        addEvent(window, 'scroll', function(){
            for (var i = flakes.length-1; i >= 0; i--){
                flakes[i].draw();
            }
        });
                    
    };
    
    /**
     * Function removes snow from the page
     */
    window.removeSnow = function(){
        enabled = false;
    }

    
    function Flake(path){
        this.parent = document.body;
        this.createEl(this.parent, path);              
        
        // setting size of a snowflake        
        //this.size = isOlderIe ? (9 + Math.random() * 3) : (Math.random() * 5 + 5);
        this.size = Math.random() * 5 + 5;
        this.el.style.width = Math.round(this.size) + 'px';
        this.el.style.height = Math.round(this.size) + 'px';            
        
        // setting boundaries
        this.maxLeft = document.body.offsetWidth - this.size;
        this.maxTop =  document.body.offsetHeight - this.size;                        
        
        // current positions            
        this.left = Math.random() * this.maxLeft;
        this.top = getScroll().top + 1;
        
        // y   speed
        // |  /
        // | /
        // |/ Angle
        // |-------- x
        
        // we will need this to make flakes paths
        // follow the sine wave
        //  )
        // (
        //  )
        this.angle = 1.4 + 0.2 * Math.random();
        // change of the angle per move
        this.minAngle = 1.4;
        this.maxAngle = 1.6;          
        this.angleDelta = 0.01 * Math.random();            
        
        this.speed = 2 + Math.random();                                   
    }
    
    Flake.prototype = {
        /**
         * Create a IMG element
         * @param {DOM Element} parent
         * @param {String} path to snowflakes dir
         */
        createEl : function(parent, path){
            this.el = document.createElement('img');                
            this.el.setAttribute('src', path + 'snow' + Math.floor(Math.random() * 4)+ '.gif');
                                    
            this.el.style.position = 'absolute';
            this.el.style.display = 'block';  
            this.el.style.zIndex = '99999';
                                                 
            this.parent.appendChild(this.el); 
        },
        /**
         * Calculates next position
         */
        move: function(){
            if (this.angle < this.minAngle || this.angle > this.maxAngle ){
                this.angleDelta = -this.angleDelta;
            }        
            this.angle += this.angleDelta;                     
                                       
            // calculate new positions based on speed and angle                
            this.left += this.speed * Math.cos(this.angle * Math.PI);                
            this.top -= this.speed * Math.sin(this.angle * Math.PI);                

            // check boundaries            
            // moved commented code to createSnow function for performance        
            //if (this.top < 0) this.top = this.maxTop;
            //else if (this.top > this.maxTop ) this.top = 0;
                            
            if (this.left < 0) this.left = this.maxLeft;
            else if (this.left > this.maxLeft) this.left = 0; 
        },
        /**
         * Apply new positions
         */
        draw : function(){                                      
            this.el.style.top = Math.round(this.top) + 'px'; 
            this.el.style.left = Math.round(this.left) + 'px';
        },
        /**
         * Cleans up object
         */
        remove : function(){
            // remove from dom
            this.parent.removeChild(this.el);
            // remove references
            this.el = null;
            this.parent = null;
        }           
    }                
        
})();
