(function($) {
    jQuery.extend(jQuery.easing, {
	easeOutBack: function (x, t, b, c, d, s) {
	    if (s == undefined) s = 1.70158;
	    return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	},easeOutQuint: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	}
    });
    $.fn.Zoomer = function(options) {
	
	var largeImg = false;
	
        var defaults = {
            speedView: 200,
            speedRemove: 400,
            altAnim: true,
            speedTitle: 400,
            debug: false,
	    ajaxLoader : 'assets/js/jquery-zoomer/ajax-loader.gif',
	    width: 600,
	    height: 400,
	    easing: 'easeOutQuint'
        };
        opts = $.extend(defaults, options);
        
	var t;
	
	function log(s) {
	    if (typeof console != "undefined" && typeof console.debug != "undefined" && opts.debug == true) {
		console.log(s)
	    } else {
	    //alert(s)
	    }
	}
        
        if (typeof opts.speedView != "undefined" || typeof opts.speedRemove != "undefined" || typeof opts.altAnim != "undefined" || typeof opts.speedTitle != "undefined") {
            if (opts.debug == true) {
                    log('speedView: ' + opts.speedView);
                    log('speedRemove: ' + opts.speedRemove);
                    log('altAnim: ' + opts.altAnim);
                    log('speedTitle: ' + opts.speedTitle)
            }
	}
	    
	    getViewport = function() {
		return [$(window).width(), $(window).height(), $(document).scrollLeft(), $(document).scrollTop() ];
	    };
	    
	    zoomIn = function(original,trigger){
		log('function zoomIn');
		
		showLoading = function(obj){
		    log('showLoading ');
		    obj.show();
		}
		
		loadImage = function(){
		    if (opts.debug == true) log('function loadImage()');
		    if (opts.preload && original.parent('a').attr('href') && original.isloaded != true){
			
			largeImgSrc = original.parent('a').attr('href');
			original.largeImgSrc = largeImgSrc;
			if (opts.debug == true) log('largeImg that should be loaded: '+largeImgSrc);
			
			loading = $('<img src="'+opts.ajaxLoader+'" class="loading" />').insertAfter(original).css({
			    'z-index': '101',
			    marginTop: opts.marginTop,
			    marginLeft: opts.marginLeft,
			    top: opts.itemTop  + opts.height / 2 ,
			    left: opts.itemLeft  + opts.width / 2 
			});
			
			//t = window.setTimeout(showLoading,1000);
			    $('<img />').load(function(){
				log('ready loading image: '+$(this).attr('src'));
				    if (t) window.clearTimeout(t);
				    loading.hide();
				    // ie can´t determine the dimensions if the image isn´t in the DOM
				    //placeholder = $('<div></div>').insertAfter(original).hide();
				    largeImg = $(this).insertAfter(original).hide();
				    if (original.zoomedOut != true){
					largeImg.css({
					    'z-index': '101',
					    marginTop: opts.marginTop,
					    marginLeft: opts.marginLeft,
					    top: opts.itemTop,
					    left: opts.itemLeft,
					    width: opts.width +'px',
					    height: opts.height + 'px'
					}).fadeIn(400,function(){if (opts.altAnim == true) animateTitle();});
				    }
				    else{
					original.attr('src', largeImgSrc);
					animateTitle()
				    }
				    original.isloaded = true;
			    }).attr('src', largeImgSrc);
		    }
		    else{
			if (opts.altAnim == true) animateTitle();
		    }
		};
		
		animateTitle = function(){
		    if (opts.altAnim == true) {
			if (opts.debug == true) log('animateTitle'+original);
			var a = original.attr("alt");
			if (a.length != 0) {
			    if (!opts.title) opts.title = $('<div id="gallerytitle" class="">' + a + '</div>').appendTo(document.body).hide();
			    else(opts.title.hide().html(a));
			    opts.title.css({
				'z-index': '99',
				'position': 'absolute',
				'width': opts.width  +'px',
				'top': original.offset().top + opts.height - opts.title.height(),
				'left': original.offset().left
			    }).show().animate({
				'top': original.offset().top + opts.height
			    }, opts.speedTitle)
			}
		    }
		}
		
		if(original.zoomedOut != true){
		    //return false;
		}
		var viewport = getViewport();
		if (opts.debug == true) log('Viewport:'+viewport);
		
		// get dimensions of large image from rel attribute of parental A element
		dimensions = original.parent('a').attr('rel');
		if (dimensions) {
		    dimensions = dimensions.split(',');
		    opts.width = dimensions[0];
		    opts.height= dimensions[1];
		}
		
		if (opts.debug == true) log('Dimensions of large image:'+dimensions[0]);
		
		var ratio = Math.min(Math.min(viewport[0] -60, opts.width) / opts.width, Math.min(viewport[1]-60, opts.height) / opts.height);
		
		opts.width = Math.round(ratio * opts.width);
		opts.height = Math.round(ratio * opts.height);
		
		if (opts.debug == true) log('large width with ratio: ' + opts.width);
		if (opts.debug == true) log('Bild Height with ratio: ' + opts.height);
		
		// calculate left and top position of the zoomed image
		opts.itemLeft	= opts.width 	> viewport[0] ? viewport[2] : (viewport[2] + Math.round((viewport[0] - opts.width) / 2));
		opts.itemTop	= opts.height	> viewport[1] ? viewport[3] : (viewport[3] + Math.round((viewport[1] - opts.height) / 2));
		
		triggerPos = trigger.offset();
		opts.marginLeft    = -triggerPos.left + 'px';
		opts.marginTop    = -triggerPos.top + 'px';
		
		// set z-index of parental element
		// because IE 6-7 create a new stacking context on positioned elements
		// see (bug in IE 6-7) http://therealcrisp.xs4all.nl/meuk/IE-zindexbug.html
		if (original.parent().parent().css('z-index') == 0) {
		    original.parent().parent().css({'z-index': '100'});
		};
		
		
		// if image is already loaded change the src immedietly
		if (original.isloaded == true) {
		    original.attr('src',original.largeImgSrc);
		}
		
		original.addClass('zoomed hover').css({'z-index': '100'}).stop(true,false).animate({
		    marginTop: opts.marginTop,
		    marginLeft: opts.marginLeft,
		    top: opts.itemTop,
		    left: opts.itemLeft,
		    width: opts.width +'px',
		    height: opts.height + 'px',
		    className : 'zoomed',
		    border: '0'
		}, options.speedView,opts.easing,loadImage);
	    }
	    
	    
	    zoomOut = function(original,trigger){
		if (opts.debug == true) log('function zoomOut');
		original.attr('src',original.image);
		loading.hide();

		//$(loading).remove();
		if (opts.title) opts.title.hide();
		//if (t) window.clearTimeout(t);
		original.zoomedOut = true;
		if (largeImg != false) largeImg.remove();
		
		original.css({'z-index': '0'}).removeClass("hover").stop(true,false).animate({
		    marginTop: '0',
		    marginLeft: '0',
		    top: original.top,
		    left: original.left,
		    width: original.originalWidth,
		    height: original.originalHeight,
		    className: ''
		}, opts.speedRemove,opts.easing,function(){
		    //original.fadeIn('slow');
		    //original.get(0).src = originalSrc;
		    // reset z-index of parental li (fix for IE 6-7)
		    if (original.parent().parent().css('z-index') == 100) {
			original.parent().parent().css({'z-index': '0'});
		    };
		});
	    }
	    
            return this.each(function(){
		
                var original = $(this);
		// 
		// activate this line for setting the width and height of the parental LI element, if no dimensions
		// for the image are set.
		// and put this code in your windows.onload:
		//window.onload =function(){
		//	jQuery('.thumb img').Zoomer({speedView:400,speedRemove:400,altAnim:true,speedTitle:400,easing:'easeOutQuint',debug:false,preload:true});
		//}
		//original.parent().parent('li').css({width: original.width(),height: original.height()});
		original.originalWidth = original.width();
		original.originalHeight = original.height();
		original.left = original.position().left;
		original.top = original.position().top;
                // if the clone doesn´t exist yet, then create it
                if (!original.next('img').hasClass('trigger')){
		    var trigger = $(this).clone().insertAfter($(this)).addClass('trigger');
                }
		
		original.image = original.attr('src');
		
		if (typeof $.fn.hoverIntent == "function"){
		    trigger.css({'z-index':'110','opacity':'0'}).hoverIntent(function() {
			if (opts.debug == true) log('mouseenter on: '+original.attr('src'));
			zoomIn(original,trigger);
		    }, function() {
			log('mouseleave'+original.attr('src'));
			zoomOut(original,trigger);
		    }).click(function(e){e.preventDefault();return false;});
		}
		else{
		    trigger.css({'z-index':'110','opacity':'0'}).hover(function() {
			if (opts.debug == true) log('mouseenter on: '+original.attr('src'));
			zoomIn(original,trigger);
		    }, function() {
			log('mouseleave'+original.attr('src'));
			zoomOut(original,trigger);
		    }).click(function(e){e.preventDefault();return false;});
		}
            });
    }
})(jQuery);
