(function($){
	$.fn.styleSafeHide = function(){
		return $(this).each(function(){
			var me = $(this);
			var regEx = /display: [a-zA-Z];?/ig;
			
			if(me.attr('style') && regEx.test(me.attr('style'))){
				me.attr('displayState', me.css('display'));
			}else{
				me.attr('displayState', 'auto');
			};
			me.hide();
		});
	}
	
	$.fn.styleSafeShow = function(){
		return $(this).each(function(){
			var me = $(this);
			var dState = me.attr('displayState');
			if(dState){
				if (dState != 'auto') {
					me.css('display', dState);
				}else{
					me.attr('style', (me.attr('style') ? me.attr('style').replace(/display: none;/ig, '') : '')) 
				}
				me.removeAttr('displayState');
			}else{
				if(me.css('display') == 'none'){
					me.attr('style', (me.attr('style') ? me.attr('style').replace(/display: none;/ig, '') : '')) 
				}
			}
		});
	}
	
}(jQuery));

(function($){
	var links;
	var printLinks;
	
	var embedStyleTag;
	var printStyleTag;
	
	var __disabled = false;
	var __printingElement;
	var __printControlPanel;
	
	var head;
	
	var tmpInlinePrintStyle;
	
	var __activeStyles = [];
	
	var init = function(){
		embedStyleTag = $(document.createElement('style'));
		var tmp = '';
		$('style').each(function(){
			var me = $(this);
			tmp += ("\n" +  me.text());
			me.remove();
		});
		
		head = $('head');
		
		// jQuery style.text(smth) bug in IE
		embedStyleTag.get(0).text = tmp;
		
		head.append(embedStyleTag);
		links = $('link[rel="stylesheet"]');
		
		__activeStyles.push(links);
		__activeStyles.push(embedStyleTag);
		
		$('html').keydown(function(event){
			if(event.keyCode == 27){
				if(__printControlPanel){
					__printControlPanel.close();
				}
			}
			
			if(event.keyCode == 80 && event.ctrlKey){
				disableStyles();
				enablePrintStyles();
				showPrintControlPanel();
				
				event.returnValue = false;
			}
		});
	}; 
	
	var disableStyles = function(){
		if(!__disabled){
			for(var i = 0; i < __activeStyles.length; i++){
				__activeStyles[i].remove();
			}
			__activeStyles = [];
			__disabled = true;
		}
	};
	
	var enableStyles = function(){
		if(__disabled){
			head.append(links).append(embedStyleTag);
			__activeStyles.push(links);
			__activeStyles.push(embedStyleTag);
			__disabled = false;
		}	
	};
	
	var restoreStyles = function(){
		printLinks.attr('media', 'print');
		disableStyles();
		enableStyles();
	}
	
	var enablePrintStyles = function(){
		if(!printStyleTag){
			var embedStyles = embedStyleTag.text();
			
			//printStyleTag = $(document.createElement('style'));
			var inlineReg = /@media (print|all),?[\s,a-zA-Z]*{([\s\n\r:0-9a-zA-Zа-яА-Я"'-;%{}!?\/%#]*)}/img;
			var tmp;
			var printEmbedStyle = '';
		
			//alert(embedStyles);
			while(tmp = inlineReg.exec(embedStyles)){
				printEmbedStyle += tmp[2];
			}
			
			printEmbedStyle	+= "\n@media print{#PrintControlPanelWrapper, .PrintVersionLink {display: none;}}";
			printStyleTag = $('<style>' + printEmbedStyle + '</style>');
		}
		
		printLinks = links.filter('[media="print"]');
		head.append(printStyleTag).append(printLinks);
		printLinks.attr('media', 'all');
		__activeStyles.push(printStyleTag);
		__activeStyles.push(printLinks);
		__disabled = false;
	};
	
	var showPrintControlPanel = function(options){
		var opts = $.extend({
			printButtonText: 'Печать',
			cancelButtonText: 'Отмена',
			useDefaultStyle: true,
			onPrint: function(){},
			onExit: function(){}	
		}, options);
		
		if(__printControlPanel){
			__printControlPanel.remove();
			delete __printControlPanel;
		}
		
		__printControlPanel = $(document.createElement('div')).attr('id', 'PrintControlPanelWrapper').css('position', 'fixed').
			css('bottom', 0).css('left', 0).css('width', '100%').css('z-index', 10000);
		
		__printControlPanel.close = function(){
			restoreStyles();		
			opts.onExit();

			__printControlPanel.remove();
			delete __printControlPanel;
			delete __printingElement;
			__printingElement = null;
		};
		
		var container = $(document.createElement('div')).attr('id', 'PrintControlPanelContainer').appendTo(__printControlPanel);
		if(opts.useDefaultStyle){
			container.css('padding', '0.4em').css('padding-left', '1.5em').
				css('background', '#E8E8E8').css('border-top', '2px solid #CCC');
		}
		var printButton = $(document.createElement('input')).attr('type', 'button').
			attr('id', 'printControlPanelPrintButton').val(opts.printButtonText).appendTo(container);
		var cancelButton = $(document.createElement('input')).attr('type', 'button').
			attr('id', 'printControlPanelCancelButton').val(opts.cancelButtonText).appendTo(container);
		
		printButton.click(function(){
			//__printControlPanel.hide();
			alert('?');
			window.print();
			alert('!');
			opts.onPrint();
			__printControlPanel.close();
		})
		
		cancelButton.click(function(){
			__printControlPanel.close();
		});
		$('body').prepend(__printControlPanel);		
	};
	
	$.showPrintVersion = function(options){
		var opts = $.extend(
			{
				onExit: function(){},
				onPrint: function(){}
			}, 
			options
		);
			
		disableStyles();
		enablePrintStyles();
		showPrintControlPanel({
			onExit: opts.onExit,
			onPrint: opts.onPrint
		});
	};
	
	$.fn.printVersionLink = function(){
		return $(this).each(function(){
			var _me = $(this); 
			_me.addClass('PrintVersionLink').click(function(){
				_me.hide();
				$.showPrintVersion({
					onExit: function(){_me.show()} 
				});
			});
		});
	};

	$.fn.printElement = function(){
		if (!__printingElement) {
			var res;
			var body = $('body');
			var me = $(this);
			if(me.is('html') || me.is('body')){
				throw "Element should be any DOM element but not 'html' and not 'body'. To print the whole page use 'printVersion' instead";
			}
		
			__printingElement = me;
			
			var toHide;
			var toShow = [];
			var toHideAfrer = [];
			
			var printDiv = $(document.createElement('div')).attr('id', 'TmpPrintWrapper');
			var restoreDisplay = function(){
				for(var i = 0; i < toHideAfrer.length; i++){
					toHideAfrer[i].styleSafeShow();	
				}
				toHide.styleSafeShow();
				if(printDiv){
					printDiv.empty().remove();
					delete printDiv;
				}
			}
			
			disableStyles();
			enablePrintStyles();
			
			toHide = body.children(":visible");
			toHide.styleSafeHide();
			
			var res = me.each(function(){
				printDiv.children().show();
				printDiv.html(printDiv.html() + $(this).parent().html())
				
				showPrintControlPanel({
					onExit: function(){
						restoreDisplay();
					},
					onPrint: function(){
						restoreDisplay();
						__printingElement = false;
					}
				});
			});
			printDiv.appendTo('body');
			return res;
		}else{
			return $(this);
		}
	};
	
	$(document).ready(function(){
		init();
	});
}(jQuery));
