(function($, undefined) {
	/**
	 * Provides requestAnimationFrame in a cross browser way.
	 * http://paulirish.com/2011/requestanimationframe-for-smart-animating/
	 */
	if ( !window.requestAnimationFrame ) {
		window.requestAnimationFrame = ( function() {
			return window.webkitRequestAnimationFrame ||
				window.mozRequestAnimationFrame ||
				window.oRequestAnimationFrame ||
				window.msRequestAnimationFrame ||
				function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) {
					window.setTimeout( callback, 1000 / 60 );
				};
		} )();
	}

	var layers = [],
		active = true,
    check_mouse_position = false,
		mouseX = 0, // Actual value computed on mouse move
		width = 960; // Actual value computed when the DOM is ready

	function parallax(el, options) {
		el.css('position', 'absolute');
		if (options.level !== undefined) {
			el.css('z-index', options.level);
		}
		var parent = el.parent();
		if (parent.css('position') !== 'absolute') {
			parent.css('position', 'relative');
		}
    layers.push({
       el: el
      ,distance: options.right - options.left
      ,left: options.left
    });
	}

	function doParallax() {
		var len = layers.length,
			i,
			mousePercent = mouseX / width,
			layer;

    if (check_mouse_position) {
      for (i = 0; i < len; i++) {
        layer = layers[i];
        layer.el.css({
          left: layer.left + mousePercent * layer.distance
        });
      }
    }
	}

	function loopParallax() {
		if (! active) {
			return;
		}
		requestAnimationFrame(loopParallax);
		doParallax();
	}

	function clearParallax() {
		layers = [];
	}

	function stopParallax() {
		active = false;
    check_mouse_position = true;
	}

	function startParallax() {
		active = true;
    check_mouse_position = true;
		loopParallax();
	}

	function runParallax() {
		active = true;
    check_mouse_position = false;
		loopParallax();
	}

	$(function() {
		$(document).mousemove(function(event) {
			mouseX = event.pageX;
      if (!check_mouse_position) {
        check_mouse_position = true;
      }
		});
		width = $(window).width();
		$(window).resize(function() {
			width = $(window).width();
		});
	});

	function main(options) {
		return this.each(function() {
			parallax($(this), options);
		})
	}

	/**
	 * Methods available to the plugin
	 */
	var methods = {
		main: main,
		run: runParallax,
		start: startParallax,
		stop: stopParallax,
		clear: clearParallax
	};

	/**
	 * Method dispatcher
	 */
	$.fn.parallax = function(method) {
		if (methods[method]) {
			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
	    }
		else if (typeof method === 'object' || !method) {
			return methods.main.apply(this, arguments);
		}
		else {
			$.error('Method ' +  method + ' does not exist on jQuery.parallax');
		}   
	};
})(jQuery);

