/*
Project: bCarousel
Author: Brian DiChiara
Version: 2.0
Usage: Add this js file to your site, call init() and simply give any element a class of "bcarousel"
Available Options: 
	wrapper : 'bCarousel-wrapper',	// default: bCarousel-wrapper
	target : 'carousel-target',		// default: carousel-target
	event : 'hover',				// default: click, optional hover
	speed : 600,					// default: 600
	increment: 8,					// default: 8 (for hover)
	easing : 'easeOutQuad'			// default: easeOutQuad, requires easing plugin
*/

(function( $ ) {
	// suggested selector = '.bCarousel'
	$.fn.bCarousel = function(opts) {
		var direction = 'left';
		
		var options = {
			container : 'bCarousel-container',	// default: bCarousel-wrapper
			wrapper : 'bCarousel-wrapper',		// default: bCarousel-wrapper
			target : 'carousel-target',			// default: carousel-target
			event : 'hover',					// default: click, optional hover
			controls: 'position',				// default: class, optional position (automatically uses hover)
			speed : 600,						// default: 600
			increment: 8,						// default: 8 (for hover)
			nextClass: 'forward',				// default: forward
			prevClass: 'back',					// default: back
			prevHTML: '&lt;',					// default: &lt;
			nextHTML: '&gt;',					// default: &gt;
			easing : 'easeOutQuad'				// default: easeOutQuad, requires easing plugin
		};
		
		var $target, $wrapper, $container = {};
		var is_closing = false;
		
		return this.each(function(){
			
			$target = $(this);
			
			// delay init() because webkit is just TOO f'n fast
			setTimeout(function(e){
				init(opts);
			}, 300);
			
		});
		
		
		function init(opts){
			
			_setopts(opts);
			
			$target.addClass(options.target);
			$target.css('width','50000000px'); // we assume images total width won't be larger than this
			
			setup_wrappers();
			// reset wrapper
			$wrapper = $wrapper;
			
			setTimeout(function(){
				var height = $target.outerHeight();
				set_width(height);
				add_controls();
			}, 1000);
		}
		
		function setup_wrappers(){
			$wrapper = $('<div />');
			$wrapper.addClass(options.wrapper); // Thanks Safari
			$target.wrap($wrapper);
			// reset wrapper var
			$wrapper = $target.parents('.'+options.wrapper+':first');
			
			$container = $('<div />');
			$container.css('overflow','hidden');
			$container.addClass(options.container); // Thanks Safari
			$target.wrap($container);
			// reset container var
			$container = $target.parents('.'+options.container+':first');
		}
		
		function set_width(height){
			var $last_img = $('a:last', $target);
			if($last_img.length > 0){
				var new_width = $last_img.offset().left + $last_img.width();
				$target.css('width',new_width +'px');
			}
			if($target.children(':first').outerHeight() > height || $target.outerHeight() > height){
				set_width(height);
			}
		}
		
		
		function add_controls(){
			if(options.controls == 'position'){
				var midpoint = Math.floor($wrapper.outerWidth()/2);
				var offset = $wrapper.offset().left;
				$wrapper.hover(function(e){
					var cursor_pos = e.clientX - offset;
					direction = (cursor_pos < midpoint) ? 'right' : 'left';
					move($target, cursor_pos);
				}).mousemove(function(e){
					var cursor_pos = e.clientX - offset;
					direction = (cursor_pos < midpoint) ? 'right' : 'left';
					if(!$target.is(':animated')){
						move($target, cursor_pos);
					}
				}).mouseout(function(e){
					var cursor_pos = e.clientX - offset;
					stop($target, cursor_pos);
				});
			} else {
				// build controls
				var $forward = $('<a />', {
					html : options.nextHTML,
					href : '#forward'
				});
				$forward.addClass(options.nextClass); // Thanks Safari
				$forward.addClass('control');
				
				var $back = $('<a />', {
					html : options.prevHTML,
					href : '#back'
				});
				$back.addClass(options.prevClass); // Thanks Safari
				$back.addClass('control');
				
				// attach them to the carousel
				$wrapper.prepend($forward).prepend($back);
				
				/* bind events */
				if(options.event == 'hover'){
					$forward.hover(function(over){
						direction = 'left';
						move($target);
					}, function(out){
						direction = 'left';
						stop($target);
					}).click(function(){ return false; });
					
					$back.hover(function(over){
						direction = 'right';
						move($target);
					}, function(out){
						direction = 'right';
						stop($target);
					}).click(function(){ return false; });
					
				} else {
					$forward.click(function(e){
						direction = 'left';
						move($target);
						return false;
					});
					
					$back.click(function(e){
						direction = 'right';
						move($target);
						return false;
					});
				}
			}
		}
		
		function move($target, cursor_pos){
			
			var params = calculate($target, cursor_pos);
			if(params == false){ return; }
			
			if(options.event == 'hover' || options.controls == 'position'){
				if(is_closing){
					$target.stop();
					is_closing = false;
				}
				
				if(params.distance > 0){
					var op = (direction == 'left') ? '-' : '+';
					var movement = op+'='+params.distance;
					$target.animate({
						marginLeft: movement
					}, 6, function(a){
						move($target);
					});
				}
			} else {
				$target.animate({
					marginLeft: params.placement
				}, {
					queue: false,
					duration: options.speed
				}, options.easing);
			}
		}
		
		function calculate($target, cursor_pos){
			var wrapper_width = $wrapper.outerWidth();
			var target_width = $target.outerWidth();
			var maxleft = (target_width - wrapper_width) * -1;
			
			var marginleft = parseInt($target.css('margin-left'));
			if(!marginleft){ marginleft = 0; }
			
			if(direction == 'right'){
				maxleft = 0;
				if(marginleft > maxleft) return false;
			} else if(marginleft < maxleft) return false;
			
			var distance = options.increment;
			if(options.event == 'click'){
				distance = wrapper_width;
			} else if(options.controls == 'position'){
				var midpoint = Math.floor(wrapper_width/2);
				var numerator = (cursor_pos < midpoint) ? (midpoint - cursor_pos) : cursor_pos - midpoint;
				var variable_distance = numerator / midpoint;
				//console.log(wrapper_width * variable_distance);
				//distance = distance + (wrapper_width * variable_distance);
			}
			
			var placement = (direction == 'left') ? marginleft - distance : marginleft + distance;
			
			if(direction == 'left'){
				if(placement >= maxleft){
					if(placement == marginleft){
						return false;
					}
				} else {
					distance = (maxleft - marginleft) * -1;
					placement = maxleft;
				}
			} else {
				if(placement <= maxleft){
					if(marginleft == placement){
						return false;
					}
				} else {
					distance = 0 - marginleft;
					placement = maxleft;
				}
			}
			
			return {
				maxleft : maxleft,
				marginleft : marginleft,
				distance : distance,
				placement : placement
			};
		}
		
		function stop ($target, cursor_pos){
			var do_closeout = false;
			if($target.is(':animated')){
				do_closeout = true;
			}
			
			$target.stop();
			
			if(options.event == 'hover' && do_closeout){
				is_closing = true;
				var tmp = options.increment;
				options.increment = 50;
				var params = calculate($target, cursor_pos);
				options.increment = tmp;
				if(params != false){
					var op = (direction == 'left') ? '-' : '+';
					var movement = op+'='+params.distance;
					$target.animate({ marginLeft: movement }, 400, options.easing, function(e){
						is_closing = false;
					});
				} else {
					is_closing = false;
				}
			}
		}
		
		function _setopts(opts){
			if(typeof(opts) == 'object'){
				for(var opt in opts){
					options[opt] = opts[opt];
				}
			}
		}
		
	} // end plugin
})( jQuery );
