/**
 * jQuery Plugin Slides.
 * @author NOSE		
 */
jQuery.fn.slides = function(op) {	
	
	// defaults
	var defaults =  {
			selClip:".galleryClip",
			selContainer:".gallerySlides",
			selSlide:"li",
			selButtons:".gallerySelectors",
			selButtonPrevious:".galleryPrevious",
			selButtonNext:".galleryNext",
			selSelectors:".unused",
			selCounterTotal:".galleryIndexTotal",
			selCounterCurrent:".galleryIndexCurrent",
			classPageIndicator:"unused",
			classCurrent:"current",
			classPrecurrent:"precurrent",
			classTransient:"transient",
			classVisible:"visible",
			classSelected:"selected",
			classInactive:"inactive",
			timeAnimate:450,
			timeResize:450,
			timeTouch:150,
			easingAnimate:"easeInQuad",
			easingResize:"easeOutQuad",
			easingTouch:"easeOutQuad",
			lrInc:558,
			controls_button:true,
			controls_navigator:true,
			controls_selector:true,
			controls_keyboard:true,
			controls_touch:false,
			indicators:false,
			counter:true,
			autosize:true,
			resize:false,
			ratio:0.0, 
			autoplay:false,
			replay:true,
			interval:4000
	};
	jQuery.extend(defaults, op);
	
	
	// options via rel
	if (jQuery(this).attr("rel") != null) {
		var r = jQuery(this).attr("rel");
		var options = r.split(";");
		for (var i = 0; i < options.length; i++) {
			var opt = options[i].split(":");
			switch (opt[0]) {
				case "autoplay":  if (opt[1] == "true") {defaults.autoplay=true}; break;
				case "replay":  if (opt[1] == "true") {defaults.replay=true}; break;
				case "lrInc": defaults.lrInc = parseInt(opt[1]); break;
				default: alert("Slides: undefined option."); break;
			}
		}
		
	}	
	
	// check one two one two
	if (jQuery(defaults.selSlide,elContainer).size() <= 1) {
		jQuery(defaults.selSlide,elContainer).addClass(defaults.classCurrent);
		return;	
	}	
	
	// elements
	var elSlides = jQuery(this);
	var elContainer = jQuery(defaults.selContainer,this);
	var elClip = jQuery(defaults.selClip,this);
	
	// buttons
	var elButtons = jQuery(defaults.selButtons,this);
	var elButtonPrevious = jQuery(defaults.selButtonPrevious,this);
	var elButtonNext = jQuery(defaults.selButtonNext,this);
	
	// selectors
	var elSelectors = jQuery(defaults.selSelectors,this);	
	
	// counters
	var elCounterTotal = jQuery(defaults.selCounterTotal,this);
	var elCounterCurrent = jQuery(defaults.selCounterCurrent,this);
	
	
	// vars
	var autoplay = defaults.autoplay;
	var replay = defaults.replay;
	var current = 0;
	var previous = -1;
	var slides = jQuery(defaults.selSlide,elContainer);
	var selectors = jQuery(defaults.selSelectors,elSlides);
	var indicators = new Array();
	var nbOfSlides = parseInt(slides.size());
	
	// buttons
	if (defaults.controls_button) {
		
		// actions
		jQuery(elButtonPrevious).bind("click",previousSlide);
		jQuery(elButtonNext).bind("click",nextSlide);
		
		// show/hide
		jQuery(elButtons).bind("mouseenter",showButtons);
		jQuery(elClip).bind("mouseenter",showButtons);
		jQuery(elClip).bind("mouseleave",hideButtons);
	}
	
	// selectors
	if (defaults.controls_selector) {
		
		// selectas
		jQuery(elSelectors).each(function(i,selecta){
			jQuery(selecta).bind("click",function(){return slideSelector(i);});
		});
	}
	
	// navigator
	if (defaults.controls_navigator && ! defaults.controls_touch) {
		
		// action
		jQuery(elClip).bind("click",slideNavigator);
		
		// event
		jQuery(elClip).bind("mousemove",updateNavigator);
	}
	
	// keyboard
	if (defaults.controls_keyboard) {
		
			// bind events
			jQuery(document).bind('keydown', this,function(evt){
				// right
				if (evt.keyCode == 39) {
					nextSlide();		
				}
				// left
				else if (evt.keyCode == 37) {
					previousSlide();	
				}
			});
	}
	
	// touch
	if (defaults.controls_touch) {
		
		// draggable & touchable
		jQuery(elContainer).draggable({ 
				axis: "x" 
		});
		jQuery(elContainer).touchable();
		
		// action
		jQuery(elContainer).bind("dragstart",prepareTouch);
		jQuery(elContainer).bind("dragstop",slideTouch);
	}

	
	// init
	initializeSlides();
	
	/**
	* Initializes the slides.
	*/
	function initializeSlides() {
	log("initializeSlides");	
		
		// replay
		if (replay) {
			
			// clone wars
			var el = jQuery(slides[0]).clone().appendTo(elContainer);
			slides = jQuery(defaults.selSlide,elContainer);		
		}
			
		// position
		jQuery(elContainer).css({"position":"relative","width":"100000px"});
		
		
		// page indicator
		if (defaults.indicators) {
			
			// markup
			var markupPageIndicator = "<div class='"+defaults.classPageIndicator+"'>";
			for (var p = 0; p < nbOfSlides; p++) {
				markupPageIndicator += "<span>slide "+p+"</span>";
			}
			markupPageIndicator += "</div>";
			
			// append
			jQuery(elSlides).append(markupPageIndicator);
			indicators = jQuery("."+defaults.classPageIndicator+ " span",elSlides);
		}
		
		// counter
		if (defaults.counter) {
			jQuery(elCounterTotal).html(slides.length-1);
		}
				
		// resize & update
		resize(false);
		update();	
		
		// readjust on load (Safari calculates wrong sizes on document ready...)
		jQuery(window).bind("load",function(){resize(false);});
		
		// autoplay
		if (autoplay) {
			window.setTimeout(slideAutoplay, defaults.interval-defaults.timeAnimate);
		}
	}
	
	/**
	* Autoplay.
	*/
	function slideAutoplay() {
	log("slideAutoplay");
		
		// autoplay
		if (autoplay) {		
				
			// play it again, sam
			if (current < nbOfSlides-1) {
				
				// index
				previous = current;
				current++;
				
				// animate
				animateNext();
				window.setTimeout(slideAutoplay, defaults.interval);
			}
			// replay
			else if (replay) {
				animateReplay();
				window.setTimeout(slideAutoplay, defaults.interval);
			}
			else {
				autoplay = false;
			}
		}
	}	
	
	/**
	* Slide Navigator.
	*/
	function slideNavigator(evt) {
	log("slideNavigator");
	
		// stop
		autoplay = false;

		// position
		var px = evt.pageX - jQuery(elSlides).offset().left;
		if (px < jQuery(elSlides).width()/2.0) {
			previousSlide();
		}
		else {
			nextSlide();
		}
		
		// prevent default
		return false;		
	}
	
	/**
	* Slide selector.
	*/
	function slideSelector(ind) {
	log("slideSelector");
	
		// stop
		autoplay = false;
	
		// next 
		if (ind > current) {
			previous = current;
			current = ind;
			animateNext();
		}	
		
		// previous
		if (ind < current) {
			previous = current;
			current = ind;
			animatePrevious();
		}
		
		// prevent default
		return false;
	}
	
	/**
	* Touch.
	*/
	function prepareTouch(event, ui) {
	log("prepareTouch");
	
		// stop
		autoplay = false;	
		
		// transient
		if (current < nbOfSlides-1) {
			jQuery(slides[current+1]).addClass(defaults.classTransient);
		}
	}
	function slideTouch(event, ui) {
	log("slideTouch " + ui.position.left);
		
		// size
		var s = resize(true);
		
		// constants
		var base = current*s.w + ui.position.left;
		var threshhold = s.w/3.0;
		
		// next
		if (base < - threshhold && current < nbOfSlides-1) {
			previous = current;
			current = previous+1;
			animateNext(defaults.timeTouch,defaults.easingTouch);
		}
		// previous
		else if (base > threshhold && current > 0) {
			previous = current;
			current = previous-1;
			animatePrevious(defaults.timeTouch,defaults.easingTouch);
		}
		// reset
		else {
			animateReset(defaults.timeTouch,defaults.easingTouch);
		}
		
			
	}
	

	
	/**
	* Next Slide.
	*/
	function nextSlide() {
	log("nextSlide");
	
		// stop
		autoplay = false;
		
		// check
		if (current < nbOfSlides-1) {
			
			// index
			previous = current;
			current++;
			
			// animate
			animateNext();	
		}	
		return false;
	}
	
	/**
	* Previous Slide.
	*/
	function previousSlide() {
	log("previousSlide");
	
		// stop
		autoplay = false;
		
		// check
		if (current > 0) {
			
			// index
			previous = current;
			current--;
			
			// animate
			animatePrevious();	
		}	
		return false;
	}
	
	/**
	* Animate next.
	*/
	function animateNext(time,easing) {
	log("animateNext");	

		// stop animation
		var a = jQuery(elContainer).stop();	
		
		// settings
		var animateTime = time ? time : defaults.timeAnimate;
		var animateEasing = easing ? easing :defaults.easingAnimate;

		// animate
		var s = resize(true);
		var x = - s.w*current;	
		jQuery(elContainer).animate({"left": x+"px"},animateTime,animateEasing,function(){
			// cleanup
		});
	

		// update
		update();	
	}
	
	
	/**
	* Animate previous.
	*/
	function animatePrevious(time,easing) {
	log("animatePrevious");
		
		// stop animation
		var a = jQuery(elContainer).stop();
		
		// settings
		var animateTime = time ? time : defaults.timeAnimate;
		var animateEasing = easing ? easing :defaults.easingAnimate;
		
		// transient
		for (var i = current+1; i < slides.length; i++) {
			jQuery(slides[i]).addClass(defaults.classTransient);	
		}	

		// animate
		var s = resize(true);
		var x = - s.w*current;
		jQuery(elContainer).animate({"left": x+"px"},animateTime,animateEasing,function(){
			// cleanup
			jQuery(slides).removeClass(defaults.classTransient);
		});
		
		// update
		update();
	}
	
	
	/**
	* Animate replay.
	*/
	function animateReplay(time,easing) {
	log("animateReplay");	
		
		// stop animation 
		var a = jQuery(elContainer).stop();
		
		// settings
		var animateTime = time ? time : defaults.timeAnimate;
		var animateEasing = easing ? easing :defaults.easingAnimate;

		// index
		previous = current;
		current++;
		
		// animate
		var s = resize(true);
		var x = - s.w*current;
		jQuery(elContainer).animate({"left": x+"px"},animateTime,animateEasing,function(){
			
			// cleanup
			current = 0;
			previous = -1;
			jQuery(elContainer).css("left",0);
			jQuery(slides).removeClass(defaults.classCurrent).removeClass(defaults.classPrecurrent);
			jQuery(slides[0]).addClass(defaults.classCurrent);
		});
		
		// update
		update();	
	}
	
	/**
	* Animate reset.
	*/
	function animateReset(time,easing) {
	log("animateReset");
	
		// settings
		var animateTime = time ? time : defaults.timeAnimate;
		var animateEasing = easing ? easing :defaults.easingAnimate;

		// animate
		var s = resize(true);
		var x = - s.w*current;
		jQuery(elContainer).animate({"left": x+"px"},animateTime,animateEasing,function(){
			// cleanup
			jQuery(slides).removeClass(defaults.classTransient);
		});

	}
	
	/**
	* Resizes stuff.
	*/
	function resize(animate) {
	log("resize");
		
		// size
		var s = new Object();
		s.w = defaults.lrInc;
		
		// auto resize
		if (defaults.autosize) {
			
			// current width
			s.w = jQuery(slides[current]).width();
		}
		
		// dynamic resize
		if (defaults.resize) {
			
			// size based on ratio
			s.w = jQuery(elSlides).width();
			s.h = s.w * defaults.ratio;
			
			// resize slides
			jQuery(slides).css({"width":s.w+"px","height":s.h+"px"});

			// resize slide container
			var rt = animate ? defaults.timeResize : 0;
			jQuery(elSlides).animate({"height":s.h+"px"},rt,defaults.easingResize);
		}	
			
		// return size
		return s;
	}
	
	/**
	* Updates the slides.
	*/
	function update() {
	log("update");
		
		// buttons
		updateButtons();
		
		// selector
		updateSelectors();
		
		// indicators
		updateIndicators();
		
		// counter
		updateCounter();
		
		// tag it
		for (var i = 0; i < slides.length; i++) {
			if (i < current) {
				jQuery(slides[i]).addClass(defaults.classPrecurrent);
			}
			else if (i > current) {
				jQuery(slides[i]).removeClass(defaults.classPrecurrent);
			}
		}
		jQuery(slides).removeClass(defaults.classCurrent);
		jQuery(slides[current]).addClass(defaults.classCurrent);			
	}
	
	
	
	/**
	* Controls.
	*/
	function showButtons() {
		jQuery(elButtons).addClass(defaults.classVisible);
	}
	function hideButtons() {
		jQuery(elButtons).removeClass(defaults.classVisible);
	}
	function updateButtons() {
		
		// buttons
		if (current == 0) {
			jQuery(elButtonPrevious).addClass(defaults.classInactive);
			jQuery(elSlides).css("cursor","default");
		}
		else {
			jQuery(elButtonPrevious).removeClass(defaults.classInactive);
		}
		if (current == nbOfSlides-1) {
			jQuery(elButtonNext).addClass(defaults.classInactive);
			jQuery(elSlides).css("cursor","default");
		}
		else {
			jQuery(elButtonNext).removeClass(defaults.classInactive);	
		}
		
	}
	
	/**
	* Navigator.
	*/
	function updateNavigator(evt) {
		
		// cursor
		if (defaults.controls_navigator && evt != null) {
			
			// position
			var px = evt.pageX - jQuery(elClip).offset().left;
			
			// previous
			if (px < jQuery(elClip).width()/2.0) {
				if (current > 0) {
					jQuery(elClip).css("cursor","pointer");
					return;
				}
			}
			// next
			else {
				if (current < nbOfSlides-1) {
					jQuery(elClip).css("cursor","pointer");
					return;
				}
			}
			jQuery(elClip).css("cursor","default");
		}
	}
	
	/**
	* Selector.
	*/
	function updateSelectors() {
		
		// index
		var si = current;
		if (current > selectors.length - 1) {
			si = 0;
		}
		
		// tag
		jQuery(selectors).removeClass(defaults.classSelected);
		jQuery(selectors[si]).addClass(defaults.classSelected);
	}
	
	/**
	* Indicators.
	*/
	function updateIndicators() {
		
		// indicator
		if (defaults.indicators) {
			
			// index
			var si = current;
			if (current > indicators.length -1) {
				si = 0;
			}
			
			// indicate
			jQuery(indicators).removeClass(defaults.classSelected);
			jQuery(indicators[si]).addClass(defaults.classSelected);
		}
	}
	
	/**
	* Counter.
	*/
	function updateCounter() {
		
		// counter
		if (defaults.counter) {
			// current
			jQuery(elCounterCurrent).html(current+1);
		}
	}
	
	/**
	* Debug Log.
	*/
	function log(msg) {
		//console.log(msg);
	}
			
    // chain
    return this;

};
