 
 /**
  * static class with some useful methods
  * "nest" for all other classes
  */
  
var z = {
  /**
   * returns Element if element is exists
   */
   id:function(id){
     return z.Element.id(id);
   },
   
   /**
    * copy all properties except prototype
    */
    copy:function(dst,src){
      for(key in src){
        if (key!=='prototype'){
          dst[key] = src[key];
        }
      }
    },

    forEach:function(obj,fn){
        for(key in obj){
            if (obj.constructor.prototype[key]!==obj[key]){
                if (fn(key)===false) break;
            }
        }
    }
}
 
 
 /**
  * inhetitance in JavaScript
  */
z.Class = function(){};
z.base = null;
z.Class.extend = function(obj){

    var this1 = this;
    var obj1 = function(){
        if (obj.construct!==undefined){
            obj.construct.apply(this,arguments);
        }
        else {
            if (this1.prototype.construct!==undefined){
                this1.prototype.construct.apply(this,arguments);
            }
        }
    }

    z.copy(obj1.prototype,this.prototype);
    z.copy(obj1.prototype,obj);
    z.copy(obj1,this);

    var old_constr = this1.prototype.construct;
    obj1.prototype.base = function(){
        if (this1.prototype.base){
            this.base = this1.prototype.base;
        }
        old_constr.apply(this,arguments);    
    };
    return obj1;
}

z.Class.implement = function(obj){
    z.copy(this.prototype,obj);
}   
 
 
/**
 * cross browser manitulations with element properties, events, styles
 */
z.Element = z.Class.extend({
    origin:null,
    construct:function(origin){
        this.origin = origin;
        this.css = this.style;
        this.p = this.prop;
    },
   
   /**
    * sets or gets style
    * to make all similar functions to be built similar way?
    */
    style:function(key_name,key_value){
        if(arguments.length==2){
            try {
                this.setStyle(key_name,key_value);
            }
            catch(e){
                alert("wrong property:"+key_name+":"+key_value);
            }
        }
        else {
            if (typeof(key_name)=='object'){
                var this1 = this;
                z.forEach(key_name,function(key){
                    this1.style(key,key_name[key]);
                });
            } 
            else {
                return this.getStyle(key_name);
            }
        }
    },    
    setStyle:function(key_name,key_value){
        if (Object.isIE && (key_name=='opacity')){
            this.origin.style.filter = "alpha(opacity:"+(key_value*100)+")";
        }
        else {
            this.origin.style[key_name] = key_value;
        }
    },
   /*
    * returns style
    * TODO make it crossbrowser too?
    */
    getStyle:function(key_name){
        return this.origin.style[key_name];
    },
    
   /**
    * sets or retrieve property
    *
    */
    prop:function(key_name,key_value){
        if(arguments.length==2){
            try {
                this.setProp(key_name,key_value);
            }
            catch(e){
                alert("wrong property:"+key_name+":"+key_value);
            }
        }
        else {
            if (typeof(key_name)=='object'){
                var this1 = this;
                z.forEach(key_name,function(key){
                    this1.prop(key,key_name[key]);
                });
            } 
            else {
                return this.getProp(key_name);
            }
        }    
    },

   /**
    * sets property
    */
    setProp:function(key_name,key_value){
        this.origin[key_name] = key_value;
    },
   /*
    * returns property
    * TODO make it crossbrowser too?
    */
    getProp:function(key_name){
        if (key_name=='text') return (this.origin['text'] || this.origin['innerText']); 
        return this.origin[key_name];
    },    

    hasClass:function(className){
        return this.origin.className.indexOf(className) != -1;  
    },
    addClass:function(className){
        if (!this.hasClass(className)){
            this.origin.className = this.origin.className+' '+className;
        }
    },
    removeClass:function(className){
        this.origin.className = this.origin.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1');
    },
        
    putBefore:function(el){
        if (el.origin) el = el.origin //it's z.Element
        el.parentNode.insertBefore(this.origin,el);
    },
            
    putAfter:function(el){
        if (el.origin) el = el.origin //it's z.Element
        if (el.nextSibling){
            el.parentNode.insertBefore(this.origin,el.nextSibling);
        }
        else {
            el.parentNode.appendChild(this.origin);
        }
    },
    putInto:function(el){
        if (el.origin) el = el.origin //it's z.Element
        el.appendChild(this.origin);
    },
    remove:function(el){
        if (el) {
            if (el.origin)  el = el.origin //it's z.Element
        }
        else el = this.origin;        
        el.parentNode.removeChild(el);
    }
});
 
z.Element.get = function (e){
 	if (e._x!==undefined) return e._x;
    return new z.Element(e);
};

z.Element.id = function(id){
    var e = document.getElementById(id);
    if (e){
       return this.get(e);
    }
    return null;
}

z.Element.create = function(name,props,styles){
    var el = z.Element.get(document.createElement(name));
    if (props) el.prop(props);
    if (styles) el.style(styles);
    return el;
};

 
/**
 * Browser detection
 *
 */
z.Browser = {
	Engine: {name: 'unknown', version: ''},
	Platform: {name: (navigator.platform.match(/mac|win|linux/i) || ['other'])[0].toLowerCase()}
};

if (window.opera) z.Browser.Engine = {name: 'presto', version: (document.getElementsByClassName) ? 950 : 925};
else if (window.ActiveXObject) z.Browser.Engine = {name: 'trident', version: (window.XMLHttpRequest) ? 5 : 4};
else if (!navigator.taintEnabled) z.Browser.Engine = {name: 'webkit', version: (!!(document.evaluate)) ? 420 : 419};
else if (document.getBoxObjectFor != null) z.Browser.Engine = {name: 'gecko', version: (document.getElementsByClassName) ? 19 : 18};
z.Browser.Engine[z.Browser.Engine.name] = z.Browser.Engine[z.Browser.Engine.name + z.Browser.Engine.version] = true;
if (window.orientation != undefined) z.Browser.Platform.name = 'ipod';
z.Browser.Platform[z.Browser.Platform.name] = true;

/**
 * domready event
 */
z.Document = {
    isReady:false,
    queue:[],
    
    bind:function(){
		// Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
		// If IE is used and is not in a frame
		// Continually check to see if the document is ready
		if ( z.Browser.Engine.trident && window == top ) (function(){
			if (this.isReady) return;
			try {
				// If IE is used, use the trick by Diego Perini
				// http://javascript.nwbox.com/IEContentLoaded/
				document.documentElement.doScroll("left");
			} catch( error ) {
				setTimeout( arguments.callee, 0 );
				return;
			}
			// and execute any waiting functions
			z.Document.invokeQueue();
		})();
		if ( z.Browser.Engine.presto || z.Browser.Engine.webkit ) {
			var numStyles;
			(function(){
				if (this.isReady) return;
				if ( document.readyState != "loaded" && document.readyState != "complete" ) {
					setTimeout( arguments.callee, 0 );
					return;
				}
				z.Document.invokeQueue();
			})();
			return;
		}
		if (document.addEventListener){
  			document.addEventListener( "DOMContentLoaded", function(){z.Document.invokeQueue()}, false );
		}
    },
    invokeQueue:function(){
    	this.isReady = true;
      	var i;
      		for (i=0;i<this.queue.length;i++){
        	var f = this.queue[i];
        	f();
      	}
    },
    ready:function(f){
		if (this.isReady) {
   	 		f();
    	}
    	else {
	  		this.queue.push(f);
    	}
  	}
}
z.copy(z.Document,new z.Element(document));
z.Document.bind();


z.snowflake = z.Class.extend({
    x:0,
    y:0,
    beforechange:0,
    wind:0,
    construct:function(owner,img,letter){
        this.owner = owner;
        this.initY();
        this.initX();
        this.initWind();
         
        if (letter){
            this.img = z.Element.create('span',{'innerHTML':img},{
                position:'absolute',
                top:Math.ceil(this.y)+'px',
                left:Math.ceil(this.x)+'px',
                fontFamily:'Comic Sans MS',
                fontSize:'18pt',
                color:"#cccccc"
                });
        }
        else {
            this.img = z.Element.create('img',{'src':img},{
                position:'absolute',
                top:Math.ceil(this.y)+'px',
                left:Math.ceil(this.x)+'px'
                });    
        }
        
        
        this.img.putInto(document.body);
        
        var this1 = this;
        window.setTimeout(function(){this1.doFrame()},50);
    },
    initX:function(){
        this.x = Math.random()*this.owner.width;
        
    },
    initY:function(){
        this.y = -Math.random()*this.owner.height;
    },    
    initWind:function(){
        this.beforechange = Math.ceil(Math.random()*100);
        this.wind = 2*Math.random()-1;
    },
    doFrame:function(){
        this.beforechange--;
        if (this.beforechange<0) this.initWind();
        this.x = this.x + this.wind;
        this.y++;
        
        if (this.y>this.owner.height){
            this.y = -this.img.p('clientHeight');
            this.initX();
            this.initY();
            //z.log('!');
        }
        
        this.img.style({top:Math.ceil(this.y)+'px',left:Math.ceil(this.x)+'px'});
        
        var this1 = this;
        window.setTimeout(function(){this1.doFrame()},50);
    }
});

z.snow = {
    count:30,
    height:0,
    widht:0,
    init:function(){
        /*this.area = z.Element.create('div',{},{
            'overflow':'hidden',
            'position':'absolute',
            'height':'100%',
            'width':'100%',
            'visibility':'hidden',
            //'background':'red',
            'top':'0px',
            'left':'0px'});
        this.area.putInto(document.body);*/
        var i;
        this.height = document.body.parentNode.clientHeight;
        this.width = document.body.parentNode.clientWidth-30;
        //z.log(document.body.parentNode.clientHeight);
        //this.height = document.body
        for(i=0;i<this.count/2;i++){       
            new z.snowflake(this,'images/zima/snow.gif');
            new z.snowflake(this,'images/zima/snow21.gif');
        };
        
        for(i=0;i<this.count/6;i++){       
            <!--new z.snowflake(this,'$',true);-->
            new z.snowflake(this,'*',true);
           <!-- new z.snowflake(this,'&#8356;',true);-->
        };
    }
}

z.Document.ready(function(){
    z.snow.init();
});
