(function($) {

	var _openTimeout = [];
	var _closeTimeout = [];

	$.fn.pinhaMenu = function(target, options)
	{
		if ((typeof target) == 'string')
		{
			var target = $(target);
		}
		if (target instanceof jQuery)
		{
			var anchor = $(this);

			var defaults = {
				targetPosition: 'right',
				childOf: null,
				offsetTop: 0,
				offsetLeft: 0,
				zIndex: 900,
				openEvent: 'mouseenter',
				closeEvent: 'mouseleave',
				openDelay: 0,
				closeDelay: 300,
				openSpeed: 200,
				closeSpeed: 200,
				openAnimation: $.fn.pinhaMenu.openAnimation,
				closeAnimation: $.fn.pinhaMenu.closeAnimation
			}
			var opts = $.extend(true, defaults, $.fn.pinhaMenu.defaults, options);
			var o = $.metadata ? $.extend(true, {}, opts, anchor.metadata()) : opts;

			o.offsetTop = parseInt(o.offsetTop);
			o.offsetLeft = parseInt(o.offsetLeft);

			if (isNaN(o.offsetTop) || isNaN(o.offsetLeft)){
				$.error('pinhaMenu: Please provide a valid offset for target');
			}

			if (o.childOf != null)
				if ((typeof o.childOf) == 'string')
					o.childOf = $(o.childOf);

			target.hide().detach().appendTo('body').css({'position': 'absolute', 'zIndex': o.zIndex});

			var eData = {'target': target, 'anchor': anchor, 'o': o};

			anchor.bind(o.openEvent, eData, _beforeOpenAnchor);

			anchor.bind(o.closeEvent, eData, _beforeCloseAnchor);

			target.bind(o.openEvent, eData, _beforeOpenTarget);

			target.bind(o.closeEvent, eData, _beforeCloseTarget);

			return anchor;

		} else {
			$.error('pinhaMenu: Please provide a valid target');
		}
	};

	$.fn.pinhaMenu.defaults = {
	};
	
	$.fn.pinhaMenu.openAnimation = function(anchor, target, o){
		target.stop(true, true).fadeIn(o.openSpeed);
	}
	
	$.fn.pinhaMenu.closeAnimation = function(anchor, target, o){
		target.stop(true, true).fadeOut(o.closeSpeed);
	}
	
	function _beforeOpenAnchor(e){
		var anchor = e.data.anchor;
		var target = e.data.target;
		var o = e.data.o;
		clearTimeout(_closeTimeout[anchor.attr('id')]);
		_position(anchor, target, o);
		_openTimeout[anchor.attr('id')] = setTimeout((function(){o.openAnimation(anchor, target, o)}), o.openDelay);
	}
	
	function _beforeCloseAnchor(e){
		var anchor = e.data.anchor;
		var target = e.data.target;
		var o = e.data.o;
		_closeTimeout[anchor.attr('id')] = setTimeout((function(){o.closeAnimation(anchor, target, o)}), o.closeDelay);
	}
	
	function _beforeOpenTarget(e){
		var anchor = e.data.anchor;
		var target = e.data.target;
		var o = e.data.o;
		clearTimeout(_closeTimeout[anchor.attr('id')]);
		if (o.childOf instanceof jQuery)
			clearTimeout(_closeTimeout[o.childOf.attr('id')]);
	}
	
	function _beforeCloseTarget(e){
		var anchor = e.data.anchor;
		var target = e.data.target;
		var o = e.data.o;
		if (o.childOf instanceof jQuery)
			o.childOf.trigger('mouseleave');
		_closeTimeout[anchor.attr('id')] = setTimeout((function(){o.closeAnimation(anchor, target, o)}), o.closeDelay);
	}
	
	function _position(anchor, target, o){
		switch(o.targetPosition.toLowerCase())
		{
			// Top Left
			case 'lefttop': case 'topleft': case 'lt': case 'tl':
				target.css({
					'top': anchor.offset().top - target.height() + o.offsetTop,
					'left': anchor.offset().left - target.width() + o.offsetLeft
				});
				break;
			// Top
			case 'top': case 't':
				target.css({
					'top': anchor.offset().top - target.height() + o.offsetTop,
					'left': anchor.offset().left + o.offsetLeft
				});
				break;
			// Top Right
			case 'righttop': case 'topright': case 'rt': case 'tr':
				target.css({
					'top': anchor.offset().top - target.height() + o.offsetTop,
					'left': anchor.offset().left + anchor.width() + o.offsetLeft
				});
				break;
			// Right
			case 'right': case 'r':
				target.css({
					'top': anchor.offset().top + o.offsetTop,
					'left': anchor.offset().left + anchor.width() + o.offsetLeft
				});
				break;
			// Bottom Right
			case 'rightbottom': case 'bottomright': case 'rb': case 'br':
				target.css({
					'top': anchor.offset().top + anchor.height() + o.offsetTop,
					'left': anchor.offset().left + anchor.width() + o.offsetLeft
				});
				break;
			// Bottom
			case 'bottom': case 'b':
				target.css({
					'top': anchor.offset().top + anchor.height() + o.offsetTop,
					'left': anchor.offset().left + o.offsetLeft
				});
				break;
			// Bottom Left
			case 'leftbottom': case 'bottomleft': case 'lb': case 'bl':
				target.css({
					'position': 'absolute',
					'top': anchor.offset().top + anchor.height() + o.offsetTop,
					'left': anchor.offset().left - target.width() + o.offsetLeft
				});
				break;
			// Left
			case 'left': case 'l':
				target.css({
					'top': anchor.offset().top + o.offsetTop,
					'left': anchor.offset().left - target.width() + o.offsetLeft
				});
				break;
			default:
				$.error('pinhaMenu: Please provide a valid position for target');
		}
	};

})(jQuery);

