/**
 *	jQuery Hover Image
 *	Allows to create nice hover effects on images, and serves as loader too!
 *
 *	Plugin by: Arlind Nushi
 *	Project Date: 04 Aug 2012
 *	Version: 1.0.1
**/


(function($)
{
	var self = this;
	
	var opts, effects, methods;
	
	
	// Image Wrapper (main DOM)
	var image_wrapper = $('<div class="hover_image_wrapper" />');
	var overlay = $('<div class="hover_image_overlay" />');
	
	
	// Options (Defaults)
	opts = {
		background: '#000',
		opacity: 0.8,
		
		duration: 500,
		easing: 'swing',
		
		effect: 'fade',
		
		responsive: false,
		
		icon: {
			el: $(null),
			setup: null,
			hoverIn: null,
			hoverOut: null
		},
		
		// Animation Engine
		animationEngine: 'jquery' // jquery or gsap

	};
	
	
	// Effects
	effects	= {
			
		fade: {
			hoverIn: function(overlay, width, height)
			{
				if(opts.animationEngine == 'gsap') // GreenSock Animation Platform TweenMax
				{
					var overlay_el = overlay.get(0);
					
					if(overlay_el.style.display == 'none')
					{
						overlay.show().fadeTo(0, 0);
					}
					
					TweenMax.to(overlay_el, opts.duration / 1000, {css: {autoAlpha: 1, yoyo: true}});
				}	
				else
				if(opts.animationEngine == 'jquery') // jQuery Animation Engine
				{
					overlay.fadeTo(opts.duration, 1, opts.easing);
				}
			},
			
			hoverOut: function(overlay, width, height)
			{
				if(opts.animationEngine == 'gsap') // GreenSock Animation Platform TweenMax
				{
					var overlay_el = overlay.get(0);
					
					if(overlay_el.style.display == 'none')
					{
						overlay.show().fadeTo(0, 0);
					}
					
					TweenMax.to(overlay_el, opts.duration / 1000, {css: {autoAlpha: 0, yoyo: true}});
				}	
				else
				if(opts.animationEngine == 'jquery') // jQuery Animation Engine
				{
					overlay.fadeTo(opts.duration, 0, opts.easing);
				}
			}
		}
	};
	
	
	// Methods
	methods = {
		
		init: function(_opts)
		{
			return this.each(function()
			{
				var el = $(this);
				var tag = el.get(0).tagName;
				
				// Set Custom Options
				$.extend(opts, _opts);
				
				// Image Wrapper
				var iw = image_wrapper.clone();
				var ol = overlay.clone();
				
				if(tag == 'IMG')
				{
					el.wrap(iw);
					el = iw;
				}
				
				// Get Image
				var img = el.find('> img').first();
				el.data('img', img);
				
				// If Has Icon element, clone it and add it as data object
				if(opts.icon.el.length)
					icon = opts.icon.el.clone();
				
				ol.data('icon', icon);
				
				// Call Main Functions
				methods.makeItRelative(el);
				methods.fitOverlay(el, ol);
				
				if(opts.responsive)
				{
					methods.makeItResponsive(el);
				}
								
				// If Has Icon element, clone it
				var icon = $(null);
				
				// Preload Image
				methods.loadImage(img, el);
				
				// Hide Overlay
				ol.hide();
				
				// setup events
				methods.setupHoverEvents(el);
			});
		},
		
		loadImage: function(img, el)
		{
			var src = img.attr('src');
			
			var img_load = new Image();
			img_load.src = src;
			img_load.onload = function()
			{
				var width = this.width;
				var height = this.height;
				
				var overlay = el.data('overlay');
				
				overlay.css({
					width: width,
					height: height
				}).data({width: width, height: height});
				
				
				// Overlay Setup
				if(overlay.data('icon').length && typeof opts.icon.setup == 'function')
				{
					opts.icon.setup.apply(this, [overlay.data('icon'), overlay, width, height]);
				}
			};
		},
		
		
		fitOverlay: function(el, overlay)
		{
			var img = el.find('img');
			
			var pl = parseInt(img.css('margin-left'), 10),
				pr = parseInt(img.css('margin-right'), 10), 
				pt = parseInt(img.css('margin-top'), 10), 
				pb = parseInt(img.css('margin-bottom'), 10);
			
			overlay
				.appendTo(el)
				.css({
					position: 'absolute',
					left: pl,
					right: pr,
					top: pt,
					bottom: pb,
					background: methods.fade(opts.background, opts.opacity),
					overflow: 'hidden'
				});
			
			
			el.data({
				overlay: overlay,
				width: el.width(),
				height: el.height()
			});
			
			
			// Icon Append
			var icon = overlay.data('icon');
			
			if(methods.hasIcon())
			{
				overlay.append(icon);
			}
			
		},
		
		
		makeItRelative: function(wrapper)
		{
			wrapper.css({
				position: 'relative',
				display: 'inline-block'
			});
		},	 
			 
		
		makeItResponsive: function(el)
		{	 
			$(window).bind('resize', function(ev)
			{
				var overlay = el.data('overlay');				
				var img = el.data('img');
				
				var img_w = img.width();
				var img_h = img.height();
				
				overlay.css({width: img_w, height: img_h}).data({width: img_w, height: img_h});
			});
		},	 
		
		
		setupHoverEvents: function(el)
		{
			var overlay = el.data('overlay');
			
			// onHover
			el.on('mouseenter', function(ev)
			{
				overlay.stop();
				methods.showOverlayEffect(overlay);
			});
			
			el.on('mouseleave', function(ev)
			{
				overlay.stop();
				methods.hideOverlayEffect(overlay);
			});
		},
		
		
		showOverlayEffect: function(overlay)
		{
			if(effects[opts.effect])
			{
				var o_width = overlay.data('width');
				var o_height = overlay.data('height');
				
				var icon = overlay.data('icon');
				
				// Show (With or Without Animation)
				effects[opts.effect].hoverIn.apply(this, [overlay, o_width, o_height]);
				
				if(methods.hasIcon())
				{
					if(typeof opts.icon.hoverIn == 'function')
					{
						icon.stop();
						opts.icon.hoverIn.apply(this, [icon, overlay, o_width, o_height, opts]);
					}
				}
			}
			else
			{
				overlay.show();
			}
		},
		
		
		hideOverlayEffect: function(overlay)
		{
			if(effects[opts.effect])
			{
				var o_width = overlay.data('width');
				var o_height = overlay.data('height');
				
				var icon = overlay.data('icon');
				
				// Hide (With or Without Animation)
				effects[opts.effect].hoverOut.apply(this, [overlay, o_width, o_height]);
				
				if(icon.length)
				{
					if(typeof opts.icon.hoverOut == 'function')
					{
						icon.stop();
						opts.icon.hoverOut.apply(this, [icon, overlay, o_width, o_height, opts]);
					}
				}
			}
			else
			{
				overlay.hide();
			}
		},
		
		
		// Fade Hex color to RGBA (opacity)
		fade: function(hex, opacity) 
		{
			var rgb = hex.replace('#', '');
			
			if(rgb.length == 3)
				rgb = rgb + rgb;
				
			rgb = rgb.match(/(.{2})/g);
			
			var i = 3;
			while (i--) 
			{
				rgb[i] = parseInt(rgb[i], 16);
			}
			
			if (typeof opacity == 'undefined')
			{
				return 'rgb(' + rgb.join(', ') + ')';
			}
			
			return 'rgba(' + rgb.join(', ') + ', ' + opacity + ')';
		},
		
		
		hasIcon: function()
		{
			return opts.icon.el.length ? true : false;
		}
		
	};
	

		
	// jQuery Method Name
	$.fn.imageHover = function(_opts)
	{
		if( ! _opts || typeof _opts == 'object')
		{
			methods.init.apply(this, [_opts]);
		}
	}
	
})(jQuery);