/*
Copyright (c) 2009, Chris Horikx. All rights reserved.
Code licensed under the BSD License:
*/

/**
 * The Gallery widget provides a means to automatically 
 * rotate images with many different animation types.
 *
 * @module gallery
 * @requires yahoo, dom, event, element, animation
 * @namespace YAHOO.widget
 * @title Gallery Widget
 * @beta
 */
(function () {
	var Dom = YAHOO.util.Dom,
		Event = YAHOO.util.Event,
		Lang = YAHOO.lang,
		Widget = YAHOO.widget;

	YAHOO.widget.Gallery = function(el, oConfig) {
		YAHOO.widget.Gallery.superclass.constructor.call(this, el, oConfig);
		this.setupGalleryByMarkup(oConfig);
	};
	
	var G = Widget.Gallery;
	
	var EFFECTS_POSITIONING = {
		'all' : {
			'fade' : {
				'position' : 'absolute',
				'left' : 0,
				'top' : 0,
				'display' : 'none',
				'z-index' : 10,
				'opacity' : 0
			}
		},
		'previous' : {
			'fade' : {
				'position' : 'absolute',
				'left' : 0,
				'top' : 0,
				'display' : 'none',
				'z-index' : 10,
				'opacity' : 1
			}
		},
		'current' : {
			'fade' : {
				'position' : 'absolute',
				'left' : 0,
				'top' : 0,
				'display' : '',
				'z-index' : 12,
				'opacity' : 1
			}
		},
		'next' : {
			'fade' : {
				'position' : 'absolute',
				'left' : 0,
				'top' : 0,
				'display' : '',
				'z-index' : 11,
				'opacity' : 1
			}
		}
	};
	
	var EFFECTS = {
		'current' : {
			'fade' : {
				'opacity' : {
					to : 0
				}
			}
		},
		'previous' : {
			'fade' : {
				'opacity' : {
					to : 0
				}
			}
		}
	};

	
	var augmentStyleObject = function(r, s) {s
		var a=arguments, i, p, override=a[2];
		for (p in s) { 
	
			if (override || !r[p]) {
				Dom.setStyle(r, p, s[p])
			}
		}
		Lang._IEEnumFix(r, s);
		
	};
	
	var formatError = function(error) {
		return '**Message:     ' + error.message + '\n' +
		       '**Filename:    ' + error.fileName + '\n' +
		       '**Line Number: ' + error.lineNumber + '\n' +
		       '**Stack:       ' + error.stack + '\n';
	};

	YAHOO.extend(G, YAHOO.util.Element, {
	
		_YUI_GalleryItems: [],
		ANIMATIONS: [],
		
		// Ready's the object for render
	    setupGalleryByMarkup: function(oConfig) {
			this.setupAttributes(oConfig);
	    },
		
		setupAttributes: function(oConfig) {
			
			this.setAttributeConfig('load', {
				value: oConfig.load
			});
			
			this.setAttributeConfig('rotation', {
				value: oConfig.rotation
			});
			
			this.setAttributeConfig('rotationAnimation', {
				value: this.get('rotation').animation || {
					'style' : 'fade'
				}
			}) 
			
			this.setAttributeConfig('effectsPositioning', {
				value: EFFECTS_POSITIONING
			});
			
			this.setAttributeConfig('currentItem', {
				value: oConfig.firstItem || 0
			})
			
			this.setAttributeConfig('GALLERY_ROTATION_ITERATOR', {
				value: oConfig.iteratorOffset || 1
			})
			
			this.setAttributeConfig('currentTimeout', {value: null});
			
			this.setAttributeConfig('itemsRoot', {
				value: Dom.get(this.get('load').el)
			});
			
			this.setAttributeConfig('oldItems', {
				value: this.get('itemsRoot').getElementsByTagName('li')
			});
			
			this.setAttributeConfig('dimensions', {
				value: oConfig.dimensions || {
					'x' : this.get('oldItems')[0].scrollWidth,
					'y' : this.get('oldItems')[0].scrollHeight
				}
			});
			
			this.setAttributeConfig('ANIMATIONS', {
				value: []
			});
			
		},
		
		configureGalleryRoot: function() {
			augmentStyleObject(this.get('element'), {
				'width' : this.get('dimensions').x/* + 'px'*/,
				'height': this.get('dimensions').y/* + 'px'*/ //Removed By CHORIKX 20091026
			});
			
			Dom.setStyle(this.get('itemsRoot'), 'display', 'none');
			
		},
		
		_beginSlideShow: function(rotation) {
			
			this.set('currentTimeout', YAHOO.lang.later(this.get('rotation').delay, this, function() {
				if (this.get('rotation').direction && this.get('rotation').direction === 'reverse') {
					this._togglePreviousItem({'rotation' : rotation})
				} else {
					this._toggleNextItem({'rotation' : rotation})
				}
			}));
		
		},
		
		stopCurrentTimeout: function() {
		
			this.get('currentTimeout').cancel();
		
		},
	
		_stopAnimations: function() {
			
			var flag = false;
			
			for (var x = 0; x < this.get('ANIMATIONS').length; x++) {
				if (this.get('ANIMATIONS')[x].isAnimated()) {
					flag = true;
					this.get('ANIMATIONS')[x].stop(true);
				}
			};
		
			return flag;
		},
		
		prevItem: function() {
			
			this.stopCurrentTimeout();
			this._togglePreviousItem();
			
		},
		
		_togglePreviousItem: function() {
		
			if (!this._stopAnimations()) {
			
				var iterator = this.get('GALLERY_ROTATION_ITERATOR') || 1;
				var currentItem = this.get('currentItem');
				var oldGalleryItems = this.get('oldItems');
				
				var animateFrom = currentItem;
				var animateTo = ((currentItem - iterator) < 0) ? currentItem - iterator + oldGalleryItems.length : currentItem - iterator;
				
				this._toggleItem(animateFrom, animateTo, this.get('rotation'));
				
				this.set('currentItem', animateTo);
			}
		},
		
		nextItem: function() {
			
			this.stopCurrentTimeout();
			this._toggleNextItem();
			
		},
		
		_toggleNextItem: function() {
			
			if (!this._stopAnimations()) {
			
				var iterator = this.get('GALLERY_ROTATION_ITERATOR') || 1;
				var currentItem = this.get('currentItem');
				var oldGalleryItems = this.get('oldItems');
				
				var animateFrom = currentItem;
				var animateTo = (currentItem + iterator > oldGalleryItems.length - 1) ? currentItem + iterator - oldGalleryItems.length : currentItem + iterator;
				
				this._toggleItem(animateFrom, animateTo, this.get('rotation'));
				
				this.set('currentItem', animateTo);
			}
		
		},
		
		_toggleItem: function(animateFrom, animateTo, rotation) {
			
			this.set('ANIMATIONS', []);
		
			var currentItemElement = this._YUI_GalleryItems[animateFrom];
			var nextItemElement = this._YUI_GalleryItems[animateTo];
			
			augmentStyleObject(currentItemElement, EFFECTS_POSITIONING.current[rotation.animation.style]);
			augmentStyleObject(nextItemElement, EFFECTS_POSITIONING.next[rotation.animation.style]);
	
			if (EFFECTS.next && EFFECTS.next[rotation.animation.style]) {
				this.get('ANIMATIONS').push(new YAHOO.util.Anim(
					nextItemElement, 
					EFFECTS.next[rotation.animation.style], 
					rotation.animation.duration, 
					YAHOO.util.Easing[rotation.animation.easing]
				));
			}
			if (EFFECTS.current && EFFECTS.current[rotation.animation.style]) {
				this.get('ANIMATIONS').push(new YAHOO.util.Anim(
					currentItemElement, 
					EFFECTS.current[rotation.animation.style], 
					rotation.animation.duration, 
					YAHOO.util.Easing[rotation.animation.easing]
				));
			}
			
			for (var x = 0; x < this.get('ANIMATIONS').length; x++) {
				this.get('ANIMATIONS')[x].animate();
			}
			
			var galleryObj = this;
			this.get('ANIMATIONS')[this.get('ANIMATIONS').length - 1].onComplete.subscribe(function () {

				augmentStyleObject(currentItemElement, EFFECTS_POSITIONING.previous[rotation.animation.style]);
				augmentStyleObject(nextItemElement, EFFECTS_POSITIONING.current[rotation.animation.style]);
	
				for (x in this._YUI_GalleryItems) {
					if (x != animateTo && x != animateFrom) {
						augmentStyleObject(YUI_GalleryItems[x], EFFECTS_POSITIONING.all[rotation.animation.style]);
					}
				};
			
				if (rotation.type === 'automatic') {
					try {
						galleryObj.set('currentTimeout', YAHOO.lang.later(rotation.delay, galleryObj, function() {
							if (this.get('rotation').direction && this.get('rotation').direction === 'reverse') {
								this._togglePreviousItem({'rotation' : rotation})
							} else {
								this._toggleNextItem({'rotation' : rotation})
							}
						}));
					} catch (e) {
						YAHOO.log(formatError(e))
					}
				} 
		
			});
		
		},

		render: function() {
			try {
				if (parseFloat(YAHOO.env.getVersion('yahoo').version) < parseFloat(YAHOO.env.getVersion('gallery').version)) {
					return;
				}
			} catch (e) {
				void(0);
			}
			this.configureGalleryRoot();
			// Hide old gallery items root
			YAHOO.util.Dom.setStyle(this.itemsRoot, 'display', 'none');
			
			// Remove any elements inside the new root node
			for (var x = 0; x < this.get('element').childNodes.length; x++) {
				this.get('element').removeChild(this.get('element').childNodes[x]);
			}
			
			// Append the new elements into the new root node
			for (var x = 0; x < this.get('oldItems').length; x++) {
				this.get('element').appendChild(this.composeGalleryItem(x, this.get('oldItems')[x], this.get('rotation'), (x == this.get('currentItem'))));
			};
			
			if (this.get('oldItems').length > 1)
				if (this.get('rotation').type === 'automatic') 
					this._beginSlideShow(this.get('rotation'));
				
		},
		
		composeGalleryItem : function(itemNumber, containingEl, rotation, isFirstItem) {
			// Compose a gallery item into the extensively configured elements
			var newGalleryItem = document.createElement('div');
			newGalleryItem.className = 'yuiGalleryItem';
		
			if (isFirstItem) 
				augmentStyleObject(newGalleryItem, this.get('effectsPositioning').current[this.get('rotationAnimation').style]);
			else 
				augmentStyleObject(newGalleryItem, this.get('effectsPositioning').all[this.get('rotationAnimation').style]);
		
			for (var y=0; y < containingEl.childNodes.length; y++) {
				newGalleryItem.appendChild(containingEl.childNodes[y]);
				y--;
			};
		
			this._YUI_GalleryItems.push(newGalleryItem);
		
			return newGalleryItem;
		}

	});

})();

YAHOO.register("gallery",YAHOO.widget.Gallery,{version:"2.7.0",build:"0001"})