(function($) {

     $(function() {
  	   (new home_hero('#heroshot div.heroshot')).start();
	   (new slideshow('td.hero_right div.heroshot')).start();
     });

     function home_hero(selector) {
	 var hero = new slideshow(selector, on_transition),
	     nav = $('<div class="heroshot-nav"></div>'),
	     nav_items = $.map(hero.slides, function(obj, i) {
		 return $('<a href="#' + (i + 1) + '">&bull;</a>').click(mover(hero, i)).appendTo(nav);
	     });

	 function on_transition() {
	     nav.children('.selected').removeClass('selected');
	     nav_items[hero.index].addClass('selected');
	 }

	 nav_items[0].addClass('selected');
	 hero.container.append(nav);

	 return hero;
     }

     function mover(hero, index) {
	 return function(e) {
	     e.preventDefault();
	     $(e.target).blur();
	     hero.select(index);
	 };
     }

     function slideshow(selector, on_transition) {
	 var container = $(selector),
	     items = container.children('a,img'),
	     slides = $.map(items.get(), $),
	     o = input_values(container.find('input'));

	 this.container = container;
	 this.slides = slides;
	 this.index = 0;

	 items.css({ width: container.width(), height: container.height() });

	 this.select = function(index) {
	     if (this.index != index) {
		 halt(); select(index);
	     }
	 };

	 this.loop = function(method) {
	     halt();
	     if (method !== undefined) {
		 loop_next = method && callback(method);
	     }
	     if (LIMIT > 1) {
		 resume();
	     }
	 };

	 // private properties and methods

	 var TRANSITION = o.transition || container.is('.heroshot-crossfade-True') ? 'crossfade' : null,
	     SPEED = (o.fadetime || 3) * 1000,
	     SHOWTIME = (o.showtime || 5) * 1000,
	     LIMIT = slides.length,
	     self = this,
	     timer = null,
	     loop_next = null;

	 function select(index) {
	     var prev = self.index,
		 next = Math.max(0, index) % LIMIT;

	     self.index = next;
	     transition(slides[prev], slides[next]);
	     resume();
	 }

	 function halt() {
	     timer && clearTimeout(timer);
	     timer = null;
	 }

	 function resume() {
	     timer = loop_next && setTimeout(loop_next, SHOWTIME);
	 }

	 function callback(method) {
	     return function() {
		 method.call(self);
	     };
	 }

	 on_transition = on_transition && callback(on_transition);
	 var animate = self[TRANSITION];

	 function transition(prev, next) {
	     animate.call(self, prev, next, SPEED);
	     on_transition && on_transition();
	 }
     }

     slideshow.prototype = {

	 start: function() {
	     if (this.slides.length > 1) {
		 this.loop(this.next);
	     }
	 },

	 stop: function() {
	     this.loop(false);
	 },

	 prev: function() {
	     this.select(this.index - 1);
	 },

	 next: function() {
	     this.select(this.index + 1);
	 },

	 crossfade: function(prev, next, speed) {
	     prev.fadeOut(speed);
	     next.fadeIn(speed);
	 }
     };

     function input_values(inputs) {
	 var values = {};
	 inputs.each(function() {
	     values[this.name] = $(this).val();
	 });
	 return values;
     }

})(jQuery);
