(function( $ ){
	var methods			= {};
	var $window			= null;
	var $body			= null;
	var topMssgHeight	= null;
	var settings		= null;
	
	methods.init = function(options) {
		var $this = this;
		$body = $("body");
		$window = $(window);
		
		if (options) $.extend(this.settings, options);
		settings = this.settings;
		
		var mTop, mRight, mBottom, mLeft;
		
		if (typeof(settings.margin) == 'object') {
			mTop	= settings.margin[0];
			mRight	= settings.margin[1];
			mBottom = settings.margin[2];
			mLeft	= settings.margin[3];
		}
		else {
			mTop = mRight = mBottom = mLeft = settings.margin;
		}
		
		$body.css("overflow", "hidden");
		
		var screenW	= $window.width();
		var screenH	= $(document).height();
		
		settings.onOpenStart();
		
		//////////////////////////////// Get size of element
		var pos = this.offset();
		var hPadding = parseInt(this.css('padding-right').replace('px', '')) + 
					parseInt(this.css('padding-left').replace('px', ''));
		
		var hBorders = (isNaN(parseInt(this.css('border-right-width').replace('px', ''))) ? 0 : parseInt(this.css('border-right-width').replace('px', ''))) + 
					(isNaN(parseInt(this.css('border-left-width').replace('px', ''))) ? 0 : parseInt(this.css('border-left-width').replace('px', '')));
				
		var vPadding = parseInt(this.css('padding-top').replace('px', '')) + 
					parseInt(this.css('padding-bottom').replace('px', ''));
		
		var vBorders = (isNaN(parseInt(this.css('border-top-width').replace('px', ''))) ? 0 : parseInt(this.css('border-top-width').replace('px', ''))) + 
					(isNaN(parseInt(this.css('border-bottom-width').replace('px', ''))) ? 0 : parseInt(this.css('border-bottom-width').replace('px', '')));
		
		var w = this.width() + hPadding + hBorders;
		var h = this.height() + vPadding + vBorders;
		
		//////////////////////////////// Append divs
		$body.append('<div class="af_sel af_left"></div>');
		$body.append('<div class="af_sel af_top"></div>');
		$body.append('<div class="af_sel af_right"></div>');
		$body.append('<div class="af_sel af_bottom"></div>');
		
		if (settings.showShadow) {
			$body.append('<div class="af_sel_shad af_top"></div>');
			$body.append('<div class="af_sel_shad af_bottom"></div>');
			$body.append('<div class="af_sel_shad af_left"></div>');
			$body.append('<div class="af_sel_shad af_right"></div>');
		}
		
		if (settings.mssg !== false) {
			$body.append('<div id="af_top_mssg" style="opacity: 0"><span class="af_mssg_container"><span class="af_mssg_text">'+settings.mssg+'</span></span></div>');
			$body.prepend("<div id='af_top_margin' style='clear: both; height: 0; margin: 0; padding: 0'></div>");
			
			topMssgHeight = $("#af_top_mssg").height();
			
			if (settings.showCloseButton) {
				$('<a id="af_close_button" href=#>×</a>').prependTo( $("#af_top_mssg span.af_mssg_container") );
				
				$("#af_close_button").click(function(evt) {
					evt.preventDefault();
					$this.aFocusOn("close");
				});
			}
		}
		
		// Class to IE6 fixed position
		$("head").append(
			'<style type="text/css">'+
			'.ie6-fix {'+
			"position: absolute; "+
			"top: expression(0+((e=document.documentElement.scrollTop)?e:document.body.scrollTop)+'px'); "+
			"left: expression(0+((e=document.documentElement.scrollLeft)?e:document.body.scrollLeft)+'px');}"+
			'</style>' );
		
		$(".af_sel").css({
			'position': 'absolute',
			'opacity': '0',
			'z-index': '1000'
		});
		$(".af_sel_shad").css({
			'position': 'absolute',
			'z-index': '999'
		});
		
		if (settings.mssg !== false) {
			if ($.browser.msie && $.browser.version <= 6) {
				$("#af_top_mssg").addClass("ie6-fix");
				$("#af_top_mssg").css({
					'z-index': '10001',
					'height': topMssgHeight+'px',
					'width': '100%'
				});
			}
			else {
				$("#af_top_mssg").css({
					'position': 'fixed',
					'z-index': '10001',
					'top': '0',
					'left': '0',
					'height': topMssgHeight+'px',
					'width': '100%'
				});
			}
		}
		
		//////////////////////////////// SHAPE
		$(".af_sel.af_left").css({
			'top': pos.top - mTop,
			'left': 0,
			'width': pos.left - mLeft,
			'height': h + mTop + mBottom,
			'background-position': '0px -'+(pos.top - mTop)+'px' // Fix bg
		});
		$(".af_sel.af_top").css({
			'top': 0,
			'left': 0,
			'width': screenW,
			'height': pos.top - mTop
		});
		$(".af_sel.af_right").css({
			'top': pos.top - mTop,
			'left': pos.left + w + mRight,
			'width': screenW - (pos.left + w + mRight),
			'height': h + mTop + mBottom,
			'background-position': '-'+(pos.left + w + mRight)+'px -'+(pos.top - mTop)+'px'
		});
		$(".af_sel.af_bottom").css({
			'top': pos.top + h + mBottom,
			'left': 0,
			'width': screenW,
			'height': screenH - (pos.top + h + mBottom),
			'background-position': '0 -'+(pos.top + h + mBottom)+'px'
		});
		
		//////////////////////////////// SHADOW
		if (settings.showShadow) {
			$(".af_sel_shad.af_top").css({
				'top': pos.top - mTop - 1,
				'left': pos.left - mLeft,
				'width': w + mLeft + mRight,
				'height': 1
			});
			$(".af_sel_shad.af_bottom").css({
				'top': pos.top + h + mBottom,
				'left': pos.left - mLeft,
				'width': w + mLeft + mRight,
				'height': 1
			});

			$(".af_sel_shad.af_left").css({
				'top': pos.top - mTop,
				'left': pos.left - mLeft - 1,
				'width': 1,
				'height': h + mTop + mBottom
			});
			$(".af_sel_shad.af_right").css({
				'top': pos.top - mTop,
				'left': pos.left + w + mRight,
				'width': 1,
				'height': h + mTop + mBottom
			});
		}
		
		
		//////////////////////////////// Animate appearing of the "FOCUSER"
		if (settings.mssg !== false) {
			$("#af_top_margin").animate({
				height: topMssgHeight+"px"
			}, {duration: settings.fadeInDuration, queue: false});
			$("#af_top_mssg").animate({
				opacity: "1"
			}, {duration: settings.fadeInDuration, queue: false});

			$(".af_sel, .af_sel_shad").animate({
				top: "+="+topMssgHeight+"px"
			}, {duration: settings.fadeInDuration, queue: false});
		}
		
		var toScroll = checkScrolledIntoView(pos.top-mTop, h+mTop+mBottom, topMssgHeight);
		
		topMssgHeight = (settings.mssg === false ? 0 : topMssgHeight);
		$("html, body").animate({
			scrollTop: "+="+toScroll+"px"
		}, {duration: settings.fadeInDuration, queue: false});
		
		var count = 0;
		$(".af_sel, .af_sel_shad").animate({
			opacity: settings.opacity
		}, {duration: settings.fadeInDuration, queue: false,
			complete: function(){
				if (count == 0) {
					if (settings.closeAfter !== false) {
						setTimeout(function(){$this.aFocusOn("close")}, settings.closeAfter);
					}
					settings.onOpenEnd();
					count++;
				}
			} 
		});
		
		//////////////////////////////// Close on click (or not)
		if (settings.closeOnClickOut) {
			$(".af_sel").click(function() {
				$this.aFocusOn("close");
			});
		}
	}
	
	methods.close = function() {
		settings.onCloseStart();
		
		$("#af_top_margin").animate({
			height: "0"
		}, {duration: settings.fadeOutDuration, queue: false});
		
		$(".af_sel, .af_sel_shad").animate({
			top: "-="+topMssgHeight+"px"
		}, {duration: settings.fadeOutDuration, queue: false});
		
		var count = 0;
		$(".af_sel, .af_sel_shad, #af_top_mssg").animate(
			{opacity: 0}, {duration: settings.fadeInDuration, queue: false,
			complete: function() {
				if (count == 0) {
					$(".af_sel, .af_sel_shad, #af_top_margin, #af_top_mssg").remove();
					settings.onCloseEnd();
					$body.css("overflow", "auto");
					count++;
				}
			}
		});
	}
	
	$.fn.aFocusOn = function(options) {
		this.settings = {
			margin: 2,
			opacity: 0.5,
			mssg: false,
			showShadow: true,
			closeOnClickOut: true,
			closeAfter: false,
			showCloseButton: true,
			fadeInDuration: 1000,
			fadeOutDuration: 1000,
			onOpenStart: function(){},
			onOpenEnd: function(){},
			onCloseStart: function(){},
			onCloseEnd: function(){}
		};
		
		if (methods[options]) {
			return methods[ options ].apply( this, Array.prototype.slice.call( arguments, 1 ));
		}
		else if (typeof(options) === 'object' || !options) {
			return methods.init.apply( this, arguments );
		}
		else {
			$.error( 'Method ' +  options + ' does not exist on jQuery.aFocusOn' );
			return null;
		}
	};
	
	function checkScrolledIntoView(elemTop, elemH, topMssgHeight) {
		var docViewTop = $window.scrollTop();
		var docViewCenter = docViewTop + $window.height()/2;
		var toScroll = 0;

		var elemBottom = elemTop + elemH;
		var elemMiddle = elemTop + elemH/2;

		if (elemMiddle > docViewCenter) {
			toScroll = (elemMiddle - docViewCenter ) + topMssgHeight;
		}
		else if (elemMiddle < docViewCenter) {
			toScroll = -(docViewCenter - elemMiddle);
		}

		return toScroll;
	}
	
})( jQuery );


/**
 * Bugs:
 * 
 * 1. In IE with zoom different to 100% may appear 1px separation betwen the divs
 */
