/* TIRotator: the Tierra Interactive Rotator
   Rotates through a selection of items using a simple opacity transition
   
   Arguments:
   items (array or selector): if an array, rotator will try to load each array
     item as an image or HTML fragment; if a string it will use it as a selector to populate
     the array with pre-existing items on the page
   
   parent (element or ID): the common parent for the elements; necessary
     for dynamic Ajax loading, otherwise can be empty or null
   
   options (object): any options you wish to override; options include:
       - duration (int): number of seconds between transitions
       - initial_delay (int): number of seconds to delay the first image (rotation
         starts after duration + initial_delay)
       - fade_duration (int): number of seconds for the fade to last
       - shared_path (string): optional shared path for all URLs in the items array
       - transition (string): Fx.Transition string for the opacity transition
       - frame_class (string): class for the wrapper element around loaded Ajax stubs
   
   Events:
   onImageLoad(new_image, rotator)
       - new_image: the image element that was just loaded
       - rotator: the rotator element that loaded the image
*/

var TIRotator = new Class({
	Implements: [Options, Events],
	options: {
		/* Class events:
		   onStart: $empty,
		   onComplete: $empty,
		   onCancel: $empty,
		   onImageLoad: $empty,
		*/
		duration: 3,
		initial_delay: 0,
		fade_duration: 3,
		shared_path: null,
		transition: 'sine:in:out',
		autoplay: true,
		frame_class: 'rotator-frame'
	},
	items: [],
	pos: 0,
	playing: false,
	rotateTimer: null,
	
	initialize: function(items, parentEl, options) {
		// Backwards compatibility fix
		if ($chk(options.image_path)) {
			options.shared_path = options.image_path;
		}
		this.setOptions(options);
		if ($type(parentEl) && parentEl != '') {
			this.parentEl = $(parentEl);
		}
		this.pos = 0;
		if ($type(items) == 'array') {
			this.items = items;
			if (this.is_image_path(0)) {
				var first = this.parentEl.getElement('img');
				if (first) {
					first.set('id', 'item-0');
					first.set('src', this.get_item_url(0));
				} else {
					this.load();
				}
			}
		} else if ($type(items) == 'string') {
			$$(items).each(function(el, index){
				this.items.push(el);
				if (index > 0) {
					el.setStyle('opacity', 0);
				}
			}, this);
		}
		
		if (this.options.autoplay) {
			this.rotateTimer = this.rotate.delay((this.options.duration + this.options.initial_delay) * 1000, this);
			this.playing = true;
		}
	},
	
	swap_items: function(prev, next, duration) {
		var duration = ($chk(duration) ? duration : this.options.fade_duration * 1000);
		prev.get('tween', {
			property: 'opacity',
			'duration': duration
		}).start(0);
		next.get('tween', {
			property: 'opacity',
			'duration': duration
		}).start(1);
		
		// Set up next rotation
		if (this.playing)
			this.rotateTimer = this.rotate.delay((this.options.duration + this.options.fade_duration) * 1000, this);
	},
	
	rotate: function() {
		var prev;
		if ($type(this.items[this.pos]) == 'element') {
			prev = this.items[this.pos];
		} else {
			prev = $('item-' + this.pos);
		}
		this.pos++;
		if (this.pos == this.items.length) {
			this.pos = 0;
		}
		// Display it if it exists, otherwised load and display
		if ($type(this.items[this.pos]) == 'element') {
			this.swap_items(prev, this.items[this.pos]);
		} else if ($('item-' + this.pos)) {
			this.swap_items(prev, $('item-' + this.pos));
		} else {
			this.load(true, prev);
		}
	},
	
	is_image_path: function(pos) {
		if (!$type(pos)) {
			pos = this.pos;
		}
		return this.items[pos].search(/\.(jpe?g|png|gif)$/) > -1;
	},
	
	get_item_url: function(pos) {
		if (!$type(pos)) {
			pos = this.pos;
		}
		if ($type(this.options.image_path) == 'string') {
			return this.options.image_path + this.items[pos];
		} else {
			return this.items[pos];
		}
	},
	
	load: function(fade, prev) {
		var fade = ($type(fade) != 'boolean' ? false : fade);
		var rotator = this;
			
		// Check if we're loading an image or an Ajax fragment
		if (this.is_image_path()) {
			var new_image = new Asset.image(this.get_item_url(), {id: 'item-' + this.pos, onload: function() {
				if (fade) {
					new_image.setStyle('opacity', 0);
				} else {
					new_image.setStyle('opacity', 1);
				}
				new_image.inject(rotator.parentEl);
				if (fade) {
					this.swap_items(prev, new_image);
				} else if ($type(prev) == 'element') {
					prev.setStyle('opacity', 0);
				}
				this.fireEvent('imageLoad', [new_image, this]);
			}.bind(this)});
		} else {
			// Ajax fragment
			var new_div = new Element('div', {id: 'item-' + this.pos, 'class': this.options.frame_class});
			new_div.set('load', {
				evalScripts: false,
				onSuccess: function(tree, els, html, js) {
					if (fade) {
						new_div.setStyle('opacity', 0);
					} else {
						new_div.setStyle('opacity', 1);
					}
					new_div.inject(rotator.parentEl);
					if (fade) {
						this.swap_items(prev, new_div);
					} else if ($type(prev) == 'element') {
						prev.setStyle('opacity', 0);
					}
					// Fire an event here?
				}.bind(this)
			}).load(this.get_item_url());
		}
	}
});
