coss.CarouselElementBinding = {
	implementation : {
		coss_setEffectDuration : function (aDuration) {
			var t = parseInt(aDuration);
			if (isNaN(t)) t = 1000;
			t = Math.abs(t);
			this._coss_CarouselElementBinding.effectDuration = t;
		},
		
		coss_setDelay : function (aDelay) {
			var t = parseInt(aDelay);
			if (isNaN(t)) t = 4000;
			t = Math.abs(t);
			this._coss_CarouselElementBinding.delay = t;
		},
	
		coss_stop : function () {
			clearInterval(this._coss_CarouselElementBinding.interval);
		},
	
		coss_start : function () {
			var cElement = this;
			
			this.coss_stop();
			
			this._coss_CarouselElementBinding.interval = setInterval(
				function () {
					cElement._coss_CarouselElementBinding.binding.change.apply(cElement, []);
				},
				this._coss_CarouselElementBinding.delay
			);
		},
		
		coss_moveNext : function () {
			this.coss_moveToItem(this.coss_getNextItem());
		},
		
		coss_movePrevious : function () {
			this.coss_moveToItem(this.coss_getPreviousItem());
		},
		
		coss_moveToItem : function (aElement) {
			this.coss_stop();
			this._coss_CarouselElementBinding.binding.change.apply(this, [aElement]);
		},
		
		coss_getActiveItem : function () {
			var els = $('> .active', this);
			if (els.length > 0) return els[0];
			return null;
		},
		
		coss_getNextItem : function () {
			var activeItem, pendingItem, els, el;
			
			pendingItem = null;
			
			activeItem = this.coss_getActiveItem();
			if (activeItem != null) {
				els = $(activeItem).next();
				if (els.length > 0) {
					pendingItem = els[0];
				}
				else {
					els = $('> li', activeItem.parentNode);
					if (els.length > 0) {
						pendingItem = els[0];
					}
				}
			}
			
			return pendingItem;
		},
		
		coss_getPreviousItem : function () {
			var activeItem, pendingItem, els, el;
			
			pendingItem = null;
			
			activeItem = this.coss_getActiveItem();
			if (activeItem != null) {
				els = $(activeItem).prev();
				if (els.length > 0) {
					pendingItem = els[0];
				}
				else {
					els = $('> li', activeItem.parentNode);
					if (els.length > 0) {
						pendingItem = els[els.length - 1];
					}
				}
			}
			
			return pendingItem;
		},
		
		coss_getPendingItem : function () {
			return this.coss_getNextItem();
		},
		
		onBindingAttached : function (aEvent, aOptions) {
			var activeItem, el, evt;
			
			this._coss_CarouselElementBinding = {
				binding : aEvent.binding,
				delay : 4000,
				effectDuration : 1000,
				interval : null,
				activeElement : null,
				pendingElement : null
			};
			
			if (aOptions) {
				if ('onphotoactivating') $(this).bind('photoactivating', aOptions.onphotoactivating);
				if ('onphotoactive') $(this).bind('photoactive', aOptions.onphotoactive);
				if ('delay') this.coss_setDelay(aOptions.delay);
				if ('effectDuration') this.coss_setEffectDuration(aOptions.effectDuration);
			}
			
			activeItem = this.coss_getActiveItem();
			if (activeItem == null) {
				el = $('> li', this).first();
				if (el.length > 0) activeItem = el[0];
			}
			
			if (activeItem != null) {
				evt = new jQuery.Event('photoactivating');
				evt.relatedTarget = activeItem;
				$(this).trigger(evt);
				
				evt = new jQuery.Event('photoactive');
				evt.relatedTarget = activeItem;
				$(this).trigger(evt);
				
				$(activeItem).addClass('active');
			}
		}
	},
	
	change : function (aTargetItem) {
		var activeItem, pendingItem, evt;
		
		activeItem = this.coss_getActiveItem();
		
		if (activeItem != null) {
			pendingItem = aTargetItem ? aTargetItem : this.coss_getPendingItem();
		
			if (pendingItem != null && pendingItem !== activeItem) {
				this._coss_CarouselElementBinding.activeElement = activeItem;
				this._coss_CarouselElementBinding.pendingElement = pendingItem;
				
				$(pendingItem).addClass('pending');
				$('> a', pendingItem).first().animate({opacity:1}, 0);
				
				evt = new jQuery.Event('photoactivating');
				evt.relatedTarget = pendingItem;
				$(this).trigger(evt);
				
				$('> a', activeItem).first().animate(
					{opacity:0},
					{
						duration : this._coss_CarouselElementBinding.effectDuration,
						complete : this._coss_CarouselElementBinding.binding.handleEffectComplete
					}
				);
			}
		}
	},
	
	handleEffectComplete : function () {
		var evt;
		var listEl = this.parentNode.parentNode;
		$(listEl._coss_CarouselElementBinding.pendingElement).removeClass('pending').addClass('active');
		$(listEl._coss_CarouselElementBinding.activeElement).removeClass('active');
		
		evt = new jQuery.Event('photoactive');
		evt.relatedTarget = listEl._coss_CarouselElementBinding.pendingElement;
		$(listEl).trigger(evt);
	}
};

coss.CarouselControllerElementBinding = {
	implementation : {
		coss_getCarousel : function () {
			return this._coss_CarouselControllerElementBinding.carousel;
		},
	
		coss_setCarousel : function (aCarousel) {
			this._coss_CarouselControllerElementBinding.carousel = aCarousel;
			
			var cController = this;
			$(aCarousel).bind('photoactivating', function (aEvent) {
				coss.CarouselControllerElementBinding.setSelectedItem(cController, aEvent.relatedTarget);
			});
			
			coss.CarouselControllerElementBinding.setSelectedItem(this, aCarousel.coss_getActiveItem());
		},
	
		onBindingAttached : function (aEvent) {
			var els, i;
			
			this._coss_CarouselControllerElementBinding = {
				carousel : null	
			};
			
			els = $('> li > a', this);
			for (i = 0; i < els.length; i++) {
				$(els[i]).bind('click', aEvent.binding.handleThumbClick);
			}
		}
	},
	
	handleThumbClick : function (aEvent) {
		this.parentNode.parentNode.coss_getCarousel().coss_moveToItem(
			document.getElementById(this.href.match(/#(.+)/)[1])
		);
		
		aEvent.preventDefault();
	},
	
	setSelectedItem : function (aController, aItem) {
		var el;
		
		$('> li', aController).removeClass('state-selected');
		
		el = $('> li > a[href~="#' + aItem.id + '"]', aController);
		if (el.length > 0) el = el[0].parentNode;
		$(el).addClass('state-selected');
	}
};
