(function($) {

$.fn.gpng = function(settings) {
	
	var defaults = {};
	
	if (settings) $.extend(defaults, settings);

	/* Load png here, using cache */
	var PNGload = function(node){
	
		if( !document.PNGcache ){
			try {document.execCommand("BackgroundImageCache", false, true);}
			catch(error) {}/* IE fix with background images cache */
			document.PNGcache = new Array();
		}
	
		/* Check if image in cache */
		for( var i=0; i<document.PNGcache.length; i++ ){
			if( document.PNGcache[i].url == node.PNGsrc ){
				if( document.PNGcache[i].loaded ) PNGset(node, document.PNGcache[i]) /* fix when image in cache */
				else document.PNGcache[i].nodes.push(node); /* or put node to cache for initialize all in the same time */
				return;
			}
		}
		/* Or push new image to cache */
		document.PNGcache.push({ url: node.PNGsrc, nodes: [node], loaded: false });
		
		/* Call preload function on DOM ready, cause we need to modified DOM */
		PNGpreload(node);
	
	}
	
	/* Preload image for calculate dimensions */
	var PNGpreload = function( node ){
		if( node.PNGsrc ){
			//var $this = jQuery(this).get(0);
			
			/* Create image node and set big negative left and top (if image too big) */
			var image = document.createElement("img");
			image.runtimeStyle.cssText = "behavior:none;position:absolute;left:-10000px;top:-10000px;border:none;";
	
			document.body.appendChild( image );
			image.onload = function() {
				var nodes;
	
				/* Looking for nodes in cache */
				for( var i=0; i<document.PNGcache.length; i++ ){
					if( document.PNGcache[i].url == node.PNGsrc ){
						nodes = document.PNGcache[i].nodes;
						break;
					}
				}
				
				/* Set dimensions of image */
				document.PNGcache[i].width = image.offsetWidth;
				document.PNGcache[i].height = image.offsetHeight;
	
				/* Initialize nodes with the same image */
				if( nodes ){
					for( var k=0; k<nodes.length; k++ ){
						PNGset(nodes[k], document.PNGcache[i])
					}
				}
				
				document.PNGcache[i].loaded = true;
				image.parentNode.removeChild(image);
			};
			image.src = node.PNGsrc; /* IE fix with onload event (src must be declared under onload event) */
		}
	}
	
	/* Set dimensions for node */
	var PNGset = function( node, cache ){
		node.PNGvml.style.width = cache.width + "px";
		node.PNGvml.style.height = cache.height + "px";
		PNGinsert(node);
	}
	
	/* Insert VML with PNG */
	var PNGinsert = function( node ){
		node.insertBefore(node.PNGvml, node.firstChild);
		PNGupdate(node);
	}
	
	/*
		Declare basic events:
			— mouse over
			— mouse out
			— propery change for all parent nodes (reaction for class changes)
	 */
	var PNGbindevents = function(node){
		node.attachEvent('onmouseenter', function( event ){
			var node = event.srcElement;
			setTimeout(function() { PNGupdate(node); }, 1);
		});
	
		node.attachEvent('onmouseleave', function( event ){
			var node = event.srcElement;
			setTimeout(function() { PNGupdate(node); }, 1);
		});
	
		node.attachEvent('onpropertychange', PNGpropertychange);
	
		var parent = node;
		while( parent = parent.parentNode ){
			if( parent )
				parent.attachEvent('onpropertychange', function( event ){
				PNGpropertychange(event, node);
			})
		}
	}
	
	/* If node change class property -> update */
	var PNGpropertychange = function( event, node ){
		if(event.propertyName == 'className'){
			var node = node ? node : event.srcElement;
			setTimeout(function() { PNGupdate(node); }, 1); 
		}
	}
	
	var PNGupdate = function( node ){
		//var $this = jQuery(this).get(0);
	
		var image = node.getElementsByTagName("image")[0];
		
		if(image){
			image.style.position = "absolute";
			image.style.display = "block";
			image.style.zIndex = "-1";
			image.style.fontSize = "0";
	
			var imageX = node.currentStyle.backgroundPositionX;
			if(imageX != "right"){
				image.style.left = imageX != 'left' ? imageX : 0;
				image.style.right = "auto";
			} else {
				image.style.left = "auto";
				image.style.right = 0;
			}
	
			var imageY = node.currentStyle.backgroundPositionY;
			if(imageY != "bottom"){
				image.style.top = imageY != "top" ? imageY : 0;
				image.style.bottom = "auto";
			} else {
				image.style.top = "auto";
				image.style.bottom = 0;
			}
		}
	}
	
	//
	
	this.each(function() {
		
		//var element = jQuery(this).get(0);
		
		this.runtimeStyle.zoom = "1"; /* one-time called expression, at the same time declare hasLayout */
		
		this.PNGvml = document.createElement("v:image");
		this.PNGsrc = this.currentStyle.backgroundImage.replace(/[^'"]*"?'?([^'"]*).*/, "$1");
		this.PNGvml.src = this.PNGsrc;

		PNGload(this);
		PNGbindevents(this);

		this.runtimeStyle.backgroundImage = "none"; /* remove background */
		
	});
	
	return this;
	
};

})(jQuery);