/*!

 * Karmic Flow 0.1

 * http://www.karmagination.com

 * Released under the MIT, BSD, and GPL Licenses - Choose one that fit your needs

 * Copyright (c) 2009 Kean L. Tan 

 * Start date: 2009-07-20

 * Build date: 2009-09-02

*/

 

(function karmicFlow($){$.fn.karmicFlow = function(opts){

	// default options

	opts = $.extend({

		container: 'karmic_flow_container',

		slider: 'karmic_flow_slider',

		slides: 'karmic_flow_slides',

		sliding: 'karmic_flow_sliding',

		slide_selected: 'karmic_flow_slide_selected',

		slide_overflow: 'karmic_flow_slide_overflow',

		controller: 'karmic_flow_controller',

		controller_selected: 'karmic_flow_controller_selected',

		next: 'karmic_flow_next_controller',

		prev: 'karmic_flow_prev_controller',

		play: 'karmic_flow_play_controller',

		pause: 'karmic_flow_pause_controller',

		duration: 300,

		timer: 2500,

		auto: false

	}, opts || {});

	

	this.data('opts', opts);

	this.data('cur_index', this.data('cur_index') || 0);



	var playSlide = function(el, auto){

		

		var $el = $(el),

			target_container = $el.attr('target'),

			$container = $('#'+target_container),

			$slider = $container.children(),

			$current_selected = $container.find('.'+opts.slide_selected),

			$allSlides = $current_selected.parent().children(),

			index = $allSlides.index($current_selected),

			total = $allSlides.length,

			old_idx = $container.data('cur_index'),

			duration = $container.data('opts').duration,

			multiplier = 1;



		

		// -1 means not found.. just quit

		if (index == -1) return false;

		

		if (auto || $el.hasClass(opts.next))

			index = (index + 1 == total) ? 0 : index + 1;

		else if ($el.hasClass(opts.prev))

			index = (index == 0) ? total - 1 : index - 1;

			

		$container.data('cur_index', index);

		

		$allSlides.removeClass(opts.slide_selected);

		$allSlides.eq(index).addClass(opts.slide_selected);

		

		var $controller_target = $('[href=#'+ $allSlides.eq(index).attr('name') + ']'),

			$controller_siblings = $('[target=' + $controller_target.attr('target') + ']');

		

		$controller_siblings.removeClass(opts.controller_selected);

		$controller_target.addClass(opts.controller_selected);

		

		$slider.addClass(opts.sliding);

		

		if((index == 0 && old_idx == total-1) || (index == total-1 && old_idx == 0)) {

			multiplier = total;

		}

		

		

		

		$slider.stop().animate({

			marginLeft: -1 * $current_selected.width() * index

		}, duration * multiplier, function(){

			$slider.removeClass(opts.sliding);	

		});

		

		return $controller_target[0];

	}



	for(var i=0; i < this.length; i++) {

		$(this[i]).find('.'+ opts.slides).each(function(){

			var $div = $('<div></div>');

			$div

			 .append(this.childNodes)

			 .appendTo(this)

			 .addClass(opts.slide_overflow)

			 .css('height', $(this).parent().parent().height());

		});

	}

	

	// first time init, we want delegate all those controllers with different class name so they know their purpose

	// we do not want to delegate twice

	var $doc = $();

	if (!$doc.data('karmic_flow_init')) {

		$doc.data('karmic_flow_init', 1);



		$doc.bind('click', function(e){

			var el = e.target,

				$el = $(el),

				target_container = $el.attr('target');

			

			// slide controller

			if ($el.hasClass(opts.controller)) {

				var $container = $('#' + target_container), 

					$found_slide = $container.find('[name=' + el.hash.substring(1, el.hash.length) + ']'),

					index = $found_slide.parent().children().index($found_slide[0]),

					$slider = $found_slide.parent(),

					old_index = $container.data('cur_index'),

					duration = $container.data('opts').duration,

					timer = $container.data('opts').timer;



				$('[target=' + target_container + ']').removeClass(opts.controller_selected);

				$el.addClass(opts.controller_selected);

				$slider.children().removeClass(opts.slide_selected);

				$found_slide.addClass(opts.slide_selected);

				$slider.addClass(opts.sliding);

				$container.data('cur_index', index);

				

				var marginLeft = -1 * $found_slide.width() * index;

				$slider.stop().animate({ marginLeft: -1 * $found_slide.width() * index }, duration * Math.abs(index-old_index), function(){

					$slider.removeClass(opts.sliding);	

				});

				// prevent default and stop propagation

				e.preventDefault();

			}

			// next button, flawed, should use current selected or will be off

			else if ($el.hasClass(opts.next) || $el.hasClass(opts.prev)) {

				playSlide(el);

				// prevent default and stop propagation

				e.preventDefault();

			}

			

			// play button

			else if ($el.hasClass(opts.play)) {

				var curEl = el,

					$container = $('#' + target_container),

					timer = $container.data('opts').timer;

				

				if($container.data('interval') !== null) {

					clearInterval($container.data('interval'));

					$container.data('interval', null);

					$el.removeClass(opts.pause);

				}

				else {

					$el.addClass(opts.pause);

					$container.data('player', curEl);

					$container.data('interval', setInterval(function(){

						$container.data('player', playSlide($container.data('player'), true));

					}, timer));

				}

				// prevent default and stop propagation

				e.preventDefault();

			}



			// other normal anchors should not be affected and behave normally so no return false, prevent default or stop propagation here

		});

	}

	

	for (var i=0; i < this.length; i++) {

		var $container = $(this[i]),

			$slider = $container.children(),

			$slides = $slider.height($container.height()).children(),

			timer = $container.data('opts').timer;

		

		$slider.width($slides.length * $container.width());

		$slides.width($container.width());



		if (opts.auto) {

			// find the play button for current container

			var $play_button = $('.'+opts.play).filter('[target=' + this[i].id + ']')

			

			// if not found, create one and hide it, we use fake play button to simulate a true button action

			if(!$play_button.length)

				$play_button = $('<a href="#" target="' + this[i].id + '" class="' + opts.next + '">&nbsp;</a>');

			

			// var curEl = $play_button[0];

			$container.data('player', $play_button[0]);

			

			// loop the slides

			$container.data('interval', setInterval(function(){

				$container.data('player', playSlide($container.data('player'), true));

			}, timer));

		}

	}

	

	// make this plugin chainable

	return this; 



}})(this.jQuery||this.Karma);
