﻿(function($){
    	
	var methods = {
		init: function(options) {
			var self = $(this);
			
			function animateVertical(element, settings, root) {
				var root = root ? root : element.position().top;
				var properties = function (pos) { return { top: pos }; };
				var callback = function () { animateVertical(element, settings, root); };

				animateLinear(element, settings, root, properties, callback);
			}

			function animateHorizontal(element, settings, root) {
				var root = root ? root : element.position().left;
				var properties = function (pos) { return { left: pos }; };
				var callback = function () { animateHorizontal(element, settings, root); };

				animateLinear(element, settings, root, properties, callback);
			}
			
			function animateLinear(element, settings, root, properties, callback) {
				var data = $.data(element, "pos");
				var pos = data ? data : root;
				
				if (pos == root + settings.offset) {
					pos = root;
				}
				else {
					pos = root + settings.offset;
				}
				
				$.data(element, "pos", pos);				
				
				element
					.stop()
					.animate(properties(pos), settings.interval, function () {
						if (settings.complete) {
							settings.complete(element);						
						}
						
						window.setTimeout(callback, 100);
					});
			}
			
			function animateRotate(element, target, settings) {
				var id = target.attr("id");
				var data = $.data(element, "settings");
				var angle = data ? data.angle : 0;
				var step = data ? data.step : 0.1;
			
				if (angle >= settings.offset) {
					step = -0.1;
				}
				else if (angle <= -settings.offset) {
					step = 0.1;
				}	
				
				angle += step;	
				
				target.rotate(step);	
				target = $("#" + id);
				
				if (settings.complete) {
					settings.complete(target);						
				}		
				
				$.data(element, "settings", { angle: angle, step: step });

				window.setTimeout(function () { 
					animateRotate(element, target, settings) 
				}, settings.interval);
			}
			
			return $.each(self, function() {
				var $this = $(this);
			
				// Resolve the settings
				var settings = $.extend({
		    		type: "",
		    		offset: 0,
					interval: 0,
		    		complete: function(element) { }
		    	}, options);
		    	
		    	// Perform the animation based on the type
		    	switch (settings.type) {
		    		case "vertical":
		    			animateVertical($this, settings);
		    			break;
		    			
		    		case "horizontal":
		    			animateHorizontal($this, settings);		    			
		    			break;
		    			
		    		case "rotate":
		    			animateRotate($this, $this, settings);
		    			break;
		    		
		    		default:
		    			$.error("Animation type " + settings.type + " does not exist");
		    			break;
		    	}
			});
		}
	};
     
	$.fn.animator = function(method) {  
    	if (methods[method]) {
			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
	    } else if (typeof method === "object" || !method) {
			return methods.init.apply(this, arguments);
	    } else {
			$.error("Method " +  method + " does not exist on jQuery.animator");
	    } 
    };     
})(jQuery);

// Depends on rotate plugin
jQuery.fn.rotate = function(angle,whence) {
	var p = this.get(0);

	// we store the angle inside the image tag for persistence
	if (!whence) {
		p.angle = ((p.angle==undefined?0:p.angle) + angle) % 360;
	} else {
		p.angle = angle;
	}

	if (p.angle >= 0) {
		var rotation = Math.PI * p.angle / 180;
	} else {
		var rotation = Math.PI * (360+p.angle) / 180;
	}
	var costheta = Math.cos(rotation);
	var sintheta = Math.sin(rotation);

	if (document.all && !window.opera) {
		var canvas = document.createElement('img');

		canvas.src = p.src;
		canvas.height = p.height;
		canvas.width = p.width;

		canvas.style.filter = "progid:DXImageTransform.Microsoft.Matrix(M11="+costheta+",M12="+(-sintheta)+",M21="+sintheta+",M22="+costheta+",SizingMethod='auto expand')";
	} else {
		var canvas = document.createElement('canvas');
		if (!p.oImage) {
			canvas.oImage = new Image();
			canvas.oImage.src = p.src;
		} else {
			canvas.oImage = p.oImage;
		}

		canvas.style.width = canvas.width = Math.abs(costheta*canvas.oImage.width) + Math.abs(sintheta*canvas.oImage.height);
		canvas.style.height = canvas.height = Math.abs(costheta*canvas.oImage.height) + Math.abs(sintheta*canvas.oImage.width);

		var context = canvas.getContext('2d');
		context.save();
		if (rotation <= Math.PI/2) {
			context.translate(sintheta*canvas.oImage.height,0);
		} else if (rotation <= Math.PI) {
			context.translate(canvas.width,-costheta*canvas.oImage.height);
		} else if (rotation <= 1.5*Math.PI) {
			context.translate(-costheta*canvas.oImage.width,canvas.height);
		} else {
			context.translate(0,-sintheta*canvas.oImage.width);
		}
		context.rotate(rotation);
		context.drawImage(canvas.oImage, 0, 0, canvas.oImage.width, canvas.oImage.height);
		context.restore();
	}
	canvas.id = p.id;
	canvas.angle = p.angle;
	p.parentNode.replaceChild(canvas, p);
}

jQuery.fn.rotateRight = function(angle) {
	this.rotate(angle==undefined?90:angle);
}

jQuery.fn.rotateLeft = function(angle) {
	this.rotate(angle==undefined?-90:-angle);
}


