//----------------------------------------------------------
//$Date: 2008-11-09 19:47:09 -0500 (Sun, 09 Nov 2008) $
//$Author: sig $
//$Revision: 68 $
//----------------------------------------------------------
//------------------------------------------------
// Javascript Library
//------------------------------------------------
if (!Array.prototype.indexOf)
{
  Array.prototype.indexOf = function(elt /*, from*/)
  {
    var len = this.length >>> 0;

    var from = Number(arguments[1]) || 0;
    from = (from < 0)
         ? Math.ceil(from)
         : Math.floor(from);
    if (from < 0)
      from += len;

    for (; from < len; from++)
    {
      if (from in this &&
          this[from] === elt)
        return from;
    }
    return -1;
  };
}

/**
 * Custom namespace creation function
 * @class EW
 */
function namespace() {
    var a=arguments, o=null, i, j, d;
    for (i=0; i<a.length; i=i+1) {
        d=a[i].split(".");
        o=window;
        for (j=0; j<d.length; j=j+1) {
            o[d[j]]=o[d[j]] || {};
            o=o[d[j]];
        }
    }
    return o;
};

/**
 * Base class
 * @class EW
 */
var EW = function() {
	var Dom = YAHOO.util.Dom
	
	// Public Methods
	return {
		// name: fadeOut
		// description: 
		fadeOut: function(ev, config) {
		
			// stop default event
			Event.stopEvent(ev);
		
			// define fade out
			var fade = new YAHOO.util.Anim(config.el, {opacity: {from:1, to:0}}, .4);
			
			// subscribe to completion of fadeout event
			fade.onComplete.subscribe(function () {
				// change window location
				window.location = Dom.get(config.link).href;
			});
			
			// fire fade out animation
			fade.animate();
		
		}, //end fadeOut
		
		// name: fadeIn
		// description: 
		fadeIn: function(ev, config) {
		
			// stop default event
			Event.stopEvent(ev);
		
			// define fade out
			var fade = new YAHOO.util.Anim(config.el, {opacity: {from:0, to:1}}, .4);
					
			// fire fade out animation
			fade.animate();
		
		}//end fadeOut
	}; // end of return call
}();

/**
 * Carousel class
 * @class EW.Carousel
 */
namespace("EW");
EW.Carousel = function() {

	// Dom shortcut
	var Dom = YAHOO.util.Dom;
	
	// this reference fix
	var self = this;
	
	// stores media
	this._media;	
	
	// stores config
	this._config;
	
	// counter for generating unique ids
	this._counter = 1;	
	
	// rotating containers
	this._container_el;
	this._prev_el;
	this._prev_el_swap;
	this._cur_el;
	this._cur_el_swap;
	this._next_el;
	this._next_el_swap;
	this._holder;
	
	// info container
	this._info;
	
	// other view container
	this._otherviews;
	
	// Private Methods
	// name: createSlide
	// create elements for a slide and return reference
	function createSlide() {
		// create main slide
		var slide = new YAHOO.util.Element(document.createElement('div'));
		Dom.setAttribute(slide, 'id', uniqId());
		
		// create internal swap div
		var swap = new YAHOO.util.Element(document.createElement('div'));
		Dom.setAttribute(swap, 'class', 'swap');
		
		// make swap div child of main slide
		slide.appendChild(swap);
		
		// return slide
		return slide;
		
	}// end function createSlide
	
	// name: getBgImageURL
	// description: gets background image value from
	// and element and parses background image style property of "url" text wrap
	function getBgImageURL(elem) {
		var cur_image = Dom.getStyle(elem, 'backgroundImage');	
		
		if (cur_image) {
			var url = cur_image.substring(4, (cur_image.length -1));
			var url2 = url.replace('"', "");
			return url2.replace('"', "");
		} else {
			return '';
		}
	}// end function getBgImageURL
	
	// name: hideElement
	// description: hide element by moving it out of viewport with absolute positioning
	// must use positioning and not display property
	// because using display doesn't preload background image
	function hideElement(elem) {
		Dom.setStyle(elem, 'position', 'absolute');
		Dom.setStyle(elem, 'top', '-9999px');
		Dom.setStyle(elem, 'left', '-9999px');
	}// end function hideElement
	
	
	// name: imageIndex
	// description: gets the index in media array of the image passed
	function imageIndex(url, getProp) {
		// loop through media array
		for (var i in self._media) { 
			// loop through inner array
			for (var j in self._media[i]) { 
				if ((j != 'thumb') && (j != 'info') && (self._media[i][j].url == url)) {
			    	// return current index
			    	if (getProp) {
			    		return new Array(parseInt(i), j); 	// return index and property name
			    	} else {
			    		return parseInt(i); 				// only return index
			    	}
			    	
			    }
			}// end for inner
		}//end for
		
		return null;
	}// end function imageIndex
	
	// name: loadOtherViews
	// description: switch other views buttons
	function loadOtherViews(idx) {
		// clear out other views container
		var children = Dom.getChildren(self._otherviews);
		for (var child in children) {
			self._otherviews.removeChild(children[child]);
		}
	
		// iterate over media in an index
		for (var i in self._media[idx]) {
			if (i != 'info') {
				// create wrapper span
				var span = new YAHOO.util.Element(document.createElement('span'));
				span.addClass('symbol');
				
				// create anchor
				var anchor = new YAHOO.util.Element(document.createElement('a'));
				anchor.set('href', '#');
				anchor.appendChild(document.createTextNode('+'));
				
				// add listner on click
				YAHOO.util.Event.addListener(anchor, 'click', this.change, {url: 'http://huffart.com/'+self._media[idx][i].url});
				
				// append anchor inside span
				span.appendChild(anchor);
				
				// append span to other view container
				var container = new YAHOO.util.Element(self._otherviews);
				container.appendChild(span);
				
			}
		}// end for
	
	}// end function loadOtherViews
		
	// name: preloadSlice
	// description: preload images in passed array slice
	function preloadSlice(elem, media) {
		
		// iterate through properties of media array slice
		for (var prop in media) {
			if (prop != 'info' && prop != 'thumb') { 
				setBgImage(elem, media[prop].url, media[prop].height, media[prop].width);
			}
		}
		
	}// end preloadSlice
	
	
	// name: setInfo
	// description: set the text of an info container
	function setInfo(cont_class, text) {
	
		if (self._info) {
			// get container reference
			var container = self._info.getElementsByClassName(cont_class)[0];
			
			// get all children of container and remove
			if (container.hasChildNodes()) {
				while (container.childNodes.length >= 1){
				    container.removeChild(container.firstChild);       
				}
			}
			
			// add text
			if (text) {
				container.appendChild(document.createTextNode(text));
			}
		}// end if
		
	}// end function setInfo
	
	// name: showOtherViews
	// description: set the content of other views container
	function showOtherViews(media) {
		
		if (self._otherviews) {
			// get container reference
			var container = self._otherviews;
			var tmp_cont = new YAHOO.util.Element(document.createElement('span'));
			
			// get all children of container and remove
			if (container.hasChildNodes()) {
				while (container.get('childNodes').length >= 1){
				    container.removeChild(container.get('firstChild'));       
				}
			}
			
			// drop objects into new array
			var mediaArr = new Array();
			for (var i in media) {
				if (i != 'info' && media[i].url.length > 0) {
					mediaArr.push(media[i]);
				}
			}
			
			// reverse array
			mediaArr.reverse();
			
			// init counter
			var counter = 0;
			
			// iterate through media array
			for (var i in mediaArr) {
				if (i != 'info' && mediaArr[i].url.length > 0) {
					// create span wrapper
					var span = new YAHOO.util.Element(document.createElement('span'));
					span.addClass('symbol');
					
					// create anchor link
					var anchor = new YAHOO.util.Element(document.createElement('a'));
					anchor.appendChild(document.createTextNode('+'));
					Dom.setAttribute(anchor, 'href', '#');
					
					// attach event listener
					anchor.on('click', function(ev, config){swapMediaURL(config.url)}, {url: mediaArr[i].url});
					
					// append anchor to span
					span.appendChild(anchor);
					
					// append to container
					tmp_cont.appendChild(span);
					
					counter = counter + 1;
				}
			}
			
			// add other view text and insert views backwards 
			if (counter > 1) {
				container.appendChild(tmp_cont);
				var span = new YAHOO.util.Element(document.createElement('span'));
				span.addClass('otherviews');
				span.appendChild(document.createTextNode('other views'));
				container.appendChild(span);
			} 
	
		}// end if
		
	}// end function showOtherViews
	
	// name: swapMedia
	// description: change currently displayed media
	function swapMedia(config) {
		if (config.direction) {
			swapMediaDirection(config.direction);
		} else if (config.url) {
			swapMediaURL(config.url);
		}
	}// end function swapMedia
	
	// name: swapMediaDirection
	// description: change media based on direction
	function swapMediaDirection(direction) {
		
		// figure out which element to swap
		var elem;
		var new_elem;
		if (direction > 0) {
			elem = self._next_el;
			new_elem = self._prev_el;
		} else if (direction < 0) {
			elem = self._prev_el;
			new_elem = self._next_el;
		}
		
		// show element to be faded in but set opacity to 0%
		Dom.setStyle(elem, 'opacity', 0);
		Dom.setStyle(elem, 'position', 'relative');
		Dom.setStyle(elem, 'top', '0');
		Dom.setStyle(elem, 'left', '0');
		
		// define fade in
		fadeIn = new YAHOO.util.Anim(elem, {opacity: {from: 0, to:1}}, .2);
		
		// get url of image to be faded in
		var cur_idx = imageIndex(getBgImageURL(elem)); 
		
		// determine index to use for new pic
		if (direction > 0) {
			if ((cur_idx + parseInt(direction)) > (self._media.length - 1)) {
				idx = 0;
			} else {
				idx = cur_idx + parseInt(direction);
			}
		} else if (direction < 0) {
			if ((cur_idx + parseInt(direction)) < 0) {
				idx = parseInt(self._media.length - 1);
			} else {
				idx = cur_idx + parseInt(direction);
			}
		}
		
		// switch other views buttons
		//loadOtherViews(cur_idx);
    	
		// subscribe to completion of fade in event
		fadeIn.onComplete.subscribe(function () {
			if (direction > 0) {
				// swap object pointers
				self._holder = self._next_el;
				self._next_el = self._prev_el;
				self._prev_el = self._cur_el;
				self._cur_el = self._holder;
				self._holder = '';
			} else if (direction < 0) {
				// swap object pointers
				self._holder = self._prev_el;
				self._prev_el = self._next_el;
				self._next_el = self._cur_el;
				self._cur_el = self._holder;
				self._holder = '';
			}
			
			// load new prev image in next_el container
			setBgImage(new_elem, self._media[idx].media_1.url, self._media[idx].media_1.height, self._media[idx].media_1.width);

		});
		
		// fire fade in
		fadeIn.animate();
		
		// swap media meta info display
		setInfo('caption', self._media[cur_idx].info.caption);
		setInfo('title', self._media[cur_idx].info.title);
		setInfo('description', self._media[cur_idx].info.description);
		
		// Load other views
		showOtherViews(self._media[cur_idx]);
		
		// preload other views images
		preloadSlice(self._cur_el_swap, self._media[cur_idx]);
		
	}// end function swapMediaDirection
	
	// name: swapMediaURL
	// description: change current displayed media by url
	function swapMediaURL(url) {
		// define fade out
		fadeOut = new YAHOO.util.Anim(self._cur_el, {opacity: {from: 1, to:0}}, .2);
		
		// subscribe to completion of fade in event
		fadeOut.onComplete.subscribe(function () {
			// define fade in
			fadeIn = new YAHOO.util.Anim(self._cur_el, {opacity: {from: 0, to:1}}, .2);
			
			// get index of image
			var media_info = imageIndex(url, true);
			var idx = media_info[0];
			var prop = media_info[1];
			
			// switch background of current image
			setBgImage(self._cur_el, self._media[idx][prop].url, self._media[idx][prop].height, self._media[idx][prop].width);
			
			// move current image back into view
			Dom.setStyle(self._cur_el, 'position', 'relative');
			Dom.setStyle(self._cur_el, 'top', '0px');
			Dom.setStyle(self._cur_el, 'left', '0px');
			
			// swap media meta info display
			setInfo('caption', self._media[idx].info.caption);
			setInfo('title', self._media[idx].info.title);
			setInfo('description', self._media[idx].info.description);
			
			// fire fade in
			fadeIn.animate();
		});
	
		// fire fade in
		fadeOut.animate();
		
	}// end function swapMediaURL
	
	// name: swapOther
	// description: change current displayed media by url
	function swapOther(ev, config) {
		swapMediaURL(config.url);
	}
	
	// name: setBgImage
	// description: set element background image, and resize to fit
	function setBgImage(elem, url, height, width) {
		// set styling
		Dom.setStyle(elem, 'backgroundImage', "url('"+url+"')");
		Dom.setStyle(elem, 'height', height+'px');
		Dom.setStyle(elem, 'width', width+'px');
		hideElement(elem);		
	}// end function setBgImage
	
	// name: uniqId
	// description: generate unique if based on id of wrapper element 
	function uniqId() {
		var uniqid = self._container_el.id + '_' + self._counter;
		
		// increment counter
		self._counter = parseInt(self._counter) + 1;
		
		return uniqid;
	}// end function uniqId
	
	
	// Privliged Methods
	//return {
		// name: init
		// description: initializes carousel
		this.init = function(config) {
			
			// set media array
			self._media = config.images;
			
			// get reference to main carousel container
			self._container_el = Dom.get(config.container);
			var main_container = new YAHOO.util.Element(self._container_el);
			
			// get reference to info container
			if (config.info) {
				self._info = new YAHOO.util.Element(Dom.get(config.info));
			}
			
			// get reference to other views container
			if (config.otherviews) {
				self._otherviews = new YAHOO.util.Element(Dom.get(config.otherviews));
			}
			
			// create current slide and attach to main container
			self._cur_el = createSlide();
			self._cur_el_swap = self._cur_el.getElementsByClassName('swap')[0];
			main_container.appendChild(self._cur_el);
			
			// create prev slide and attach to main container
			self._prev_el = createSlide();
			self._prev_el_swap = self._prev_el.getElementsByClassName('swap')[0];
			main_container.appendChild(self._prev_el);
			hideElement(self._prev_el);
			
			// create next slide and attach to main container
			self._next_el = createSlide();
			self._next_el_swap = self._next_el.getElementsByClassName('swap')[0];
			main_container.appendChild(self._next_el);
			hideElement(self._next_el);
			
			// create image loader group
			imgGroup = new YAHOO.util.ImageLoader.group(self._container_el, 'mouseover', .1); 
			
			// load current image
			imgGroup.registerBgImage(Dom.getAttribute(self._cur_el, 'id'), self._media[0].media_1.url);
			Dom.setStyle(self._cur_el, 'height', self._media[0].media_1.height+'px');
			Dom.setStyle(self._cur_el, 'width', self._media[0].media_1.width+'px');
			Dom.setStyle(self._cur_el, 'opacity', 0);
			imgGroup.fetch();
			
			// load current image meta info
			setInfo('caption', self._media[0].info.caption);
			setInfo('title', self._media[0].info.title);
			setInfo('description', self._media[0].info.description);
			
			// fade in current image
			fadeIn = new YAHOO.util.Anim(self._cur_el, {opacity: {from: 0, to:1}}, .5);
			
			// subscribe to completion of fade in event
			fadeIn.onComplete.subscribe(function () {
				// load previous image
				imgGroup.registerBgImage(Dom.getAttribute(self._prev_el, 'id'), self._media[self._media.length - 1].media_1.url);
				Dom.setStyle(self._prev_el, 'height', self._media[self._media.length - 1].media_1.height+'px');
				Dom.setStyle(self._prev_el, 'width', self._media[self._media.length - 1].media_1.width+'px');
				
				// load next image
				if (self._media[1]) {
					imgGroup.registerBgImage(Dom.getAttribute(self._next_el, 'id'), self._media[1].media_1.url);
					Dom.setStyle(self._next_el, 'height', self._media[1].media_1.height+'px');
					Dom.setStyle(self._next_el, 'width', self._media[1].media_1.width+'px');
				}
				
				// fetch all images
				imgGroup.fetch();
				
				// preload additional pics within cur, prev and next slices
				preloadSlice(self._cur_el_swap, self._media[0]);
				if (self._media[1]) {
					preloadSlice(self._next_el_swap, self._media[1]);
				}
				if (self._media[self._media.length - 1]) {
					preloadSlice(self._prev_el_swap, self._media[self._media.length - 1]);
				}
				
				// Load other views
				showOtherViews(self._media[0]);
			
			});
			
			// fire fade in
			fadeIn.animate();
			
		}; //end function init
		
		// name: change
		// description: switches carousel media
		this.change = function(ev, config) {
			// stop default event
			Event.stopEvent(ev);
						
			// define fade out
			var fadeOut = new YAHOO.util.Anim(self._cur_el, {opacity: {from:1, to:0}}, .2);
			
			// subscribe to completion of fadeout event
			fadeOut.onComplete.subscribe(function () {
				
				// hide element that just faded
				hideElement(self._cur_el);		
				
				// swap out media	
				swapMedia(config);
				
			});
			
			// fire fade animation
			fadeOut.animate(); 
			
		};// end function change
		
	//};// end of return call for public methods
}; // end EW.Carousel
