/*
	Author: Joe Nicora
	www.seemecreate.com
	-------------------
	Attribution-Share Alike 3.0 United States
	You are free:
		* to Share — to copy, distribute, display, and perform the work
		* to Remix — to make derivative works
	Under the following conditions:
		* Attribution. You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work).
		* Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under the same, similar or a compatible license.
		* For any reuse or distribution, you must make clear to others the license terms of this work. The best way to do this is with a link to this web page.
		* Any of the above conditions can be waived if you get permission from the copyright holder.
		* Apart from the remix rights granted under this license, nothing in this license impairs or restricts the author's moral rights.
		
	http://creativecommons.org/licenses/by-sa/3.0/us/
	* version: 1.3
*/
// build/photoviewer_base.js
// set up short cuts into the global namespace
var lib = {};
lib.d = YAHOO.util.Dom;
lib.e = YAHOO.util.Event;
lib.ce = YAHOO.util.CustomEvent;
lib.a = YAHOO.util.Anim;
// photoviewer base object
YAHOO.namespace("YAHOO.photoViewer");
// instance object

YAHOO.photoViewer.base = function(id){
	// dom
	var container = null; // thumb container
	var viewerDom = null;
	var maskDom = null; // overlay (viewer) mask
	var showcaseImage = null;
	var headerDom = null;
	var titleDom = null;
	var closeDom = null;
	var bodyDom = null;
	var descDom = null;
	var footerDom = null;
	var prevDom = null;
	var nextDom = null;
	// yui objects
	var viewer = null;
	// collections
	var thumbs = null; // collection of thumbs in thumb container
	// storage
	var that = this;
	var properties = YAHOO.photoViewer.config.viewers[id].properties;
	var events = {}; // storage for custom events
	var currentThumb = null;
	var preloadtimer = null;
	var preloadimgs = [];
	var hasLoaded = {};
	var defaultText = {next:"next", prev:"prev", close:"close"};

	// public
	this.init = function(){
		// check loadfrom
		if (properties.loadFrom == "xml"){
			setEvents();
		}
		if (properties.loadFrom == "html"){
			config();
		}
		return this;
	}; // load init
	this.loadXML = function(url){
		var sUrl = url ? url : properties.url;
		var postData = "";
		var callback = {
		  success: readPhotos,
		  failure: fail,
		  that: this
		};
		YAHOO.photoViewer.loading.on();
		var request = YAHOO.util.Connect.asyncRequest('GET', sUrl, callback, postData);
	}; // end loadXML
	this.prev = function(){		
		var currentIndex = getThumbIndexFromId(currentThumb);
		var prevousIndex = (currentIndex > 0) ? (currentIndex - 1) : (thumbs.length - 1);
		currentThumb = thumbs[prevousIndex].getElementsByTagName("img")[0];
		loadViewer(thumbs[prevousIndex]);
	}; // end prev
	this.next = function(){
		var currentIndex = getThumbIndexFromId(currentThumb);
		var nextIndex = (currentIndex < (thumbs.length - 1)) ? (currentIndex + 1) : 0;
		currentThumb = thumbs[nextIndex].getElementsByTagName("img")[0];
		loadViewer(thumbs[nextIndex]);
	}; // end next
	this.close = function(){
		viewer.hide();
		lib.d.setStyle(maskDom, "visibility", "hidden");
	}; // end close
	this.open = function(index){
		var thumb = currentThumb ? currentThumb.parentNode : thumbs[0];
		var index = Number(index);
		if (index > -1 && index < thumbs.length){
			thumb = thumbs[index];
		}
		currentThumb = thumb.getElementsByTagName("img")[0];
		loadViewer(thumb);
		viewer.show();
	}; // end open
	this.on = function(evt, callback){
		events[evt].subscribe(callback);
	}; // end on
	this.un = function(evt, callback){
		events[evt].unsubscribe(callback);
	}; // end on
	this.getProperty = function(p){
		if (!properties[p]){ return null; }
		return properties[p]
	}; // end getProperty
	this.setProperty = function(p, v){
		if (!properties[p]){ return null; }
		properties[p] = v;
		return properties[p]
	}; // end getProperty
	this.preload = function(){		
		var func = "YAHOO.photoViewer.controller.getViewer('"+properties.id+"').preload()";
		if (preloadtimer) {
			clearTimeout(preloadtimer); 
		}		
		for (var a = 0; a < thumbs.length; a++){
			preloadimgs.push(new Image());
			preloadimgs[a].src = thumbs[a].getAttribute("href");
		}
		if (preloadimgs.length < thumbs.length)
			preloadtimer = setTimeout(func, 1000);
	}; // end preload
	// private
	/* -----------------------------*/
	/* -----------------------------*/
	function getThumbIndexFromId(el){
		return Number(lib.d.getAncestorByTagName(el, "a").getAttribute("id").split("_")[1]);
	}; // end getThumbIndexFromId
	function getThumbIndex(el){
		for (var a = 0; a < thumbs.length; a++){
			if (el === thumbs[a])
				return a;
		}
	}; // end getThumbIndex
	function loadViewer(e){
		if (!viewer){
			createViewer();
			if (YAHOO.env.ua.ie == 0 || YAHOO.env.ua.ie == 7) { lib.e.on(showcaseImage, "load", viewerLoaded); }
			else { that.checkLoadForIe(); }
		}
		var thumbImage = lib.e.getTarget(e) ? lib.e.getTarget(e) : e.getElementsByTagName("img")[0];
		var thumbAnchor = thumbImage.parentNode;
		var titleText = thumbAnchor.getAttribute("title").length ? thumbAnchor.getAttribute("title") : "";
		//var descText = thumbImage.getAttribute("alt").length ? thumbImage.getAttribute("alt") : "|";
		var descText = thumbImage.getAttribute("alt");
		var photoCount = getThumbIndexFromId(thumbImage) + 1;
		if (photoCount == (thumbs.length)){ // fire before last photo
			events.beforelastphoto.fire();
		}
		insertStr(titleDom, titleText); // set header
		insertStr(descDom.firstChild, descText); // set description
		showcaseImage.src = thumbAnchor.href; // load image!
		if (!hasLoaded[thumbAnchor.href]){ // check to see if this has loaded yet
			YAHOO.photoViewer.loading.on({applyTo:viewerDom});
		}
		/* set items hidden */
		lib.d.setStyle(bodyDom, "opacity", "0");
		lib.d.setStyle(titleDom, "opacity", "0");
		// adjust z indicies
		lib.d.setStyle(viewerDom, "z-index", YAHOO.photoViewer.zIndex++);
		lib.d.setStyle(maskDom, "z-index", YAHOO.photoViewer.zIndex - 1);
		// handle events
		if (!YAHOO.env.ua.ie != 0){ // everything but ie 6
			events.viewerupdated.unsubscribe(attachShowcaseEvts);
			events.viewerupdated.subscribe(attachShowcaseEvts);
			events.viewerupdated.fire();
		}
		else
			that.checkLoadForIe();
	}; // loadViewer
	function attachShowcaseEvts(){ // work around for ie bug
		if (!YAHOO.env.ua.ie == 0 || YAHOO.env.ua.ie == 7){ // for everything other than ie use load event for image
			lib.e.purgeElement(showcaseImage, true, "load");
			lib.e.on(showcaseImage, "load", viewerLoaded);
		}
		else{ // ie needs to use intervals and check the complete property
			checkLoadForIe();
		}
	}; 	// end attachShowcaseEvts
	
	/* bug for ie aaaaarrrrrggggghhhhhhhh!!!!!!!!!!!!! */
	var checkLoadTimeout = null;
	this.checkLoadForIe = function(){
		var func = "YAHOO.photoViewer.controller.getViewer('"+properties.id+"').checkLoadForIe()";
		if (checkLoadTimeout) {
			clearTimeout(checkLoadTimeout); 
		}
		if (!showcaseImage.complete){
			checkLoadTimeout = setTimeout(func, 1000);
		}
		else{
			viewerLoaded();
		}
	}; // end checkLoad
	/* bug for ie aaaaarrrrrggggghhhhhhhh!!!!!!!!!!!!! */
	
	function getClassName(el){
		if (!typeof el == "object") { return null; }
		if (YAHOO.env.ua.ie)
			return el.getAttribute("className");
		else
			return el.getAttribute("class");
	}; // end getClassName
	function readPhotos(data){
		var photo = {};
		if(data.responseXML !== undefined){
			var photoNodes = data.responseXML.getElementsByTagName("photo");
			for (var i = 0; i < photoNodes.length; i++){
				photo.thumbsource = photoNodes[i].getElementsByTagName("thumbsource")[0].firstChild.nodeValue;
				photo.fullsource = photoNodes[i].getElementsByTagName("fullsource")[0].firstChild.nodeValue;
				if (photoNodes[i].getElementsByTagName("title")[0].firstChild){
					photo.title = photoNodes[i].getElementsByTagName("title")[0].firstChild.nodeValue;
				}
				else{
					photo.title = "";
				}
				if (photoNodes[i].getElementsByTagName("description")[0].firstChild){
					photo.description = photoNodes[i].getElementsByTagName("description")[0].firstChild.nodeValue;
				}
				else{
					photo.description = "";
				}
				createPhoto(photo);
			}
			events.xmlload.fire();
			config();
			YAHOO.photoViewer.loading.off();
		}
	}; // end readPhotos
	function fail(data){
		alert("XML file failed to load");
		YAHOO.photoViewer.loading.off();
	}; // end fail
	function createPhoto(photo){
		var anchor = document.createElement("a");
		var img = document.createElement("img");
		container = lib.d.get(properties.id);

		anchor.setAttribute("href", photo.fullsource);
		anchor.setAttribute("title", photo.title);
		lib.d.addClass(anchor, "photoViewer");
		//lib.d.setStyle(anchor, "display", "none"); // make the devs set thumbs to hidden via css
		
		img.setAttribute("src", photo.thumbsource);
		img.setAttribute("alt", photo.description);
		
		anchor.appendChild(img);
		container.appendChild(anchor);
	}; // end createPhoto
	function config(){
		container = lib.d.get(properties.id);
		thumbs = lib.d.getElementsByClassName("photoViewer", "a", container);
		//if (properties.preload){ // run preload routine
		//}
		that.preload();
		// set events
		setEvents();
	}; // end config
	function setEvents(){
		if (thumbs){ // check if this viewer has  been configed
			// set thumb events, loop over collection
			for (var a = 0; a < thumbs.length; a++){
				lib.e.on(thumbs[a], "click", thumbClick, that, true);
				thumbs[a].setAttribute("id", "thumb_" + a);
			}
			// set window events
			lib.e.on(window, "resize", adjustPosition);
		}
		// set custom events
		if (!events.xmlload) events.xmlload = new lib.ce("xmlload", this, true, 1);
		if (!events.viewerload) events.viewerload = new lib.ce("viewerload", this, true, 1);
		if (!events.viewerupdated) events.viewerupdated = new lib.ce("viewerupdated", this, true, 1); // used to check if new viewer image has loaded
		if (!events.beforelastphoto) events.beforelastphoto = new lib.ce("beforelastphoto", this, true, 1); 
		if (!events.lastphoto) events.lastphoto = new lib.ce("lastphoto", this, true, 1);
	}; // end setEvents
	function thumbClick(e, scope){
		currentThumb = lib.e.getTarget(e);
		loadViewer(e);
		lib.e.preventDefault(e); // stop default
	}; //  end thumbClick
	function viewerLoaded(){
		if (showcaseImage.src == "" || !showcaseImage.src){
			return;
		}
		// apply modal screen
		lib.d.setStyle(maskDom, "visibility", "visible");
		// record loaded
		hasLoaded[showcaseImage.src] = true;
		var widthTo = (lib.d.getRegion(showcaseImage).right - lib.d.getRegion(showcaseImage).left) + 
			parseInt(lib.d.getStyle(imageContDom, "padding-left"), 10) +
			parseInt(lib.d.getStyle(imageContDom, "padding-right"), 10)
		;
		// show viewer
		if (!isVisible(viewerDom)){
			if (properties.fixedcenter){ // only grow if fixed center position
				lib.d.setStyle(viewerDom, "width", "10px");
				lib.d.setStyle(viewerDom, "height", "10px");
			}
			try{ viewer.center(); }catch(e) { /* bug in ie */ }
			viewer.show();
		}
		// ensure height by setting width
		lib.d.setStyle(descDom, "width", widthTo + "px");
		/* set total height for all components */
		var heightTo = 
			lib.d.getRegion(showcaseImage).bottom - lib.d.getRegion(showcaseImage).top +
			parseInt(lib.d.getStyle(imageContDom, "padding-top"), 10) +
			parseInt(lib.d.getStyle(imageContDom, "padding-bottom"), 10) +
			lib.d.getRegion(descDom).bottom - lib.d.getRegion(descDom).top +
			lib.d.getRegion(headerDom).bottom - lib.d.getRegion(headerDom).top + 
			lib.d.getRegion(footerDom).bottom - lib.d.getRegion(footerDom).top
		;
		var topTo = (lib.d.getViewportHeight()/2) - (heightTo/2) - 20 + lib.d.getDocumentScrollTop();
		var leftTo = (lib.d.getViewportWidth()/2) - (widthTo/2) - 20 + lib.d.getDocumentScrollLeft();
		var attr = {width:{to:widthTo},height:{to:heightTo},top:{to:topTo},left:{to:leftTo}};
		if (!properties.fixedcenter){ // dont update XY
			var x = eval(properties.xy)[0];
			var y = eval(properties.xy)[1];
			attr = {width:{to:widthTo},height:{to:heightTo}};
			lib.d.setStyle(viewerDom, "top", y + "px");
			lib.d.setStyle(viewerDom, "left", x + "px");
		}
		var resize = new lib.a(viewerDom, attr, properties.grow, properties.easing);
		resize.animate();
		resize.onComplete.unsubscribe(fadeViewer);
		resize.onComplete.subscribe(fadeViewer);
		// size mask
		adjustPosition();
		// clear objects
		resize = null;
		// fire event
		events.viewerload.fire();
		YAHOO.photoViewer.loading.off();
	}; // end viewerLoaded
	function fadeViewer(){
		var fade = null;
		//var domEls = [bodyDom, headerDom, footerDom];
		var domEls = [bodyDom,titleDom];
		
		for (var a = 0; a < domEls.length; a++){
			fade = new lib.a(domEls[a], {opacity:{to:1}}, properties.fade, properties.easing);
			fade.animate();
		}
		fade.onComplete.unsubscribe(finishLoad);
		fade.onComplete.subscribe(finishLoad);
		// clear objects
		fade = null;
	}; // end fade viewer
	function finishLoad(){
		if ((getThumbIndexFromId(currentThumb) + 1) == (thumbs.length)){ // fire last photo
			events.lastphoto.fire();
		}
	}; // end finishLoad
	function destroyViewer(){
		if (viewer){
			viewer.destroy();
		} 
	}; // end destroyViewer
	function createViewer(){
		var buttonText = properties.buttonText ? properties.buttonText : defaultText;
		showcaseImage = document.createElement("img");
		lib.d.addClass(showcaseImage, "photoViewer-showcaseImage");
		lib.d.addClass(showcaseImage, "photoViewer-showcase");
		if (!viewerDom){
			// build viewer
			viewerDom = document.createElement("div");
			viewerDom.setAttribute("id", properties.id + "-viewer");
			lib.d.addClass(viewerDom, "photoViewer-viewer");
			// build mask
			maskDom = document.createElement("div");
			maskDom.setAttribute("id", properties.id + "-mask");
			lib.d.addClass(maskDom, "photoViewer-mask");
			lib.d.setStyle(maskDom, "z-index", YAHOO.photoViewer.zIndex - 1);
			// build header
			headerDom = document.createElement("div");
			headerDom.setAttribute("id", properties.id + "-header");
			lib.d.addClass(headerDom, "photoViewer-header");
			// build title
			titleDom = document.createElement("h1");
			titleDom.setAttribute("id", properties.id + "-title");
			lib.d.addClass(titleDom, "photoViewer-title");
			// build close button
			closeDom = document.createElement("a");
			var closeText = buttonText.close ? buttonText.close : defaultText.close;
			insertStr(closeDom, closeText);
			closeDom.setAttribute("id", properties.id + "-close");
			closeDom.setAttribute("href", "javascript:;");
			lib.d.addClass(closeDom, "photoViewer-close");
			lib.e.on(closeDom, "click", that.close);
			// build body
			bodyDom = document.createElement("div");
			bodyDom.setAttribute("id", properties.id + "-body");
			lib.d.addClass(maskDom, "photoViewer-body");
			// build image container
			imageContDom = document.createElement("div");
			imageContDom.setAttribute("id", properties.id + "-imageCont");
			lib.d.addClass(imageContDom, "photoViewer-imageCont");
			// build despription
			descDom = document.createElement("div");
			descDom.setAttribute("id", properties.id + "-desc");
			lib.d.addClass(descDom, "photoViewer-desc");
			// build footer
			footerDom = document.createElement("div");
			footerDom.setAttribute("id", properties.id + "-footer");
			lib.d.addClass(footerDom, "photoViewer-footer");
			// build buttons
			// prev
			prevDom = document.createElement("a");
			var prevText = buttonText.prev ? buttonText.prev : defaultText.prev;
			insertStr(prevDom, prevText);
			prevDom.setAttribute("id", properties.id + "-prev");
			//prevDom.setAttribute("href", "javascript:;");
			lib.d.addClass(prevDom, "photoViewer-prev");
			lib.e.on(prevDom, "click", that.prev);
			// next
			nextDom = document.createElement("a");
			var nextText = buttonText.next ? buttonText.next : defaultText.next;
			insertStr(nextDom, nextText);
			nextDom.setAttribute("id", properties.id + "-next");
			//nextDom.setAttribute("href", "javascript:;");
			lib.d.addClass(nextDom, "photoViewer-next");
			lib.e.on(nextDom, "click", that.next);
			// append nodes
			headerDom.appendChild(titleDom);
			headerDom.appendChild(closeDom);
			bodyDom.appendChild(imageContDom);
			imageContDom.appendChild(showcaseImage);
			bodyDom.appendChild(descDom);
			descDom.appendChild(document.createElement("p")); // add paragraph
			footerDom.appendChild(prevDom);
			footerDom.appendChild(nextDom);
			if (properties.modal) { document.body.appendChild(maskDom); } // if modal switched on
			if (properties.position == "absolute" || !properties.container){
				document.body.appendChild(viewerDom);
			}
			else{
				lib.d.get(properties.container).appendChild(viewerDom);
			}
			// set up config
			// drag and drop
			if (properties.dragable){
				var dragObj = new YAHOO.photoViewer.DDOnTop(viewerDom.getAttribute("id"));
				dragObj.setHandleElId(titleDom.getAttribute("id"));
				lib.d.setStyle(titleDom, "cursor", "move");
				lib.e.on(viewerDom, "click", function(){
					lib.d.setStyle(this, "z-index", YAHOO.photoViewer.zIndex++);
				});
			}
		}
		var posXY = properties.xy ? properties.xy : null;
		var type, attr;
		if (properties.position == "absolute"){
			type = YAHOO.widget.Overlay;
			attr = { 
				xy:eval(posXY),
				fixedcenter:properties.fixedcenter,
				constraintoviewport:true,
				visible:false,  
				zIndex:YAHOO.photoViewer.zIndex, 
				effect:{effect:YAHOO.widget.ContainerEffect.FADE,duration:properties.fade} 
			};
		}
		else{
			type = YAHOO.widget.Module;
			attr = {visible:true};
			// set up positioning
			lib.d.setStyle(viewerDom, "position", "relative");
		}
		viewer =  new type(properties.id + "-viewer", attr); 
		viewer.setHeader(headerDom);
		viewer.setBody(bodyDom);
		viewer.setFooter(footerDom);
		viewer.render();
	}; // end createViewer
	function adjustPosition(){
		var width = (lib.d.getDocumentWidth() > lib.d.getViewportWidth()) ? lib.d.getDocumentWidth() : lib.d.getViewportWidth();
		var height = (lib.d.getDocumentHeight() > lib.d.getViewportHeight()) ? lib.d.getDocumentHeight() : lib.d.getViewportHeight();
		lib.d.setStyle(maskDom, "width", width + "px");
		lib.d.setStyle(maskDom, "height", height + "px");
	}; // end adjustPosition
	function isVisible(el){
		if (lib.d.getStyle(el, "visibility") == "visible")
			return true;
		else
			return false;
	}; // end isVisible
	function insertStr(el, str, append){
		var append = append ? append : false;
		if (!append && el.firstChild){
			el.removeChild(el.firstChild);
		}
		el.appendChild(document.createTextNode(str));
		//lib.d.setStyle(el, "height", lib.d.getRegion(el).bottom - lib.d.getRegion(el).top); // TODO: fix ie sizing issue
	}; // end insertStr
	function testForThumb(el){
		return lib.d.hasClass(el, "photoViewer");
	}; // end testForThumb
};
// loader class
YAHOO.photoViewer.loading = function(){
	var loadingScreen = null;
	var applyTo = null;
	var publik = {
		on: function(config){
			/* config.applyTo = element to render loading over. */
			if (!config){ config = {}; }
			applyTo = config.applyTo ? lib.d.get(config.applyTo) : document.body;
			createLoadingScreen();
		},
		off: function(){
			lib.d.setStyle(loadingScreen, "display", "none");
		}
	};
	// private
	function createLoadingScreen(){
		if (!loadingScreen){
			loadingScreen = document.createElement("div");
			loadingScreen.setAttribute("id", "photoViewer-loading");
			lib.d.addClass(loadingScreen, "photoViewer-loading");
			lib.d.setStyle(loadingScreen, "position", "absolute");
			lib.d.setStyle(loadingScreen, "display", "none");
			document.body.appendChild(loadingScreen);
		}
		position();
		lib.d.setStyle(loadingScreen, "display", "block");
		lib.d.setStyle(loadingScreen, "z-index", YAHOO.photoViewer.zIndex + 10);
	}; // end createLoadingScreen
	function position(){
		lib.d.setStyle(loadingScreen, "top", lib.d.getRegion(applyTo).top + "px");
		lib.d.setStyle(loadingScreen, "left", lib.d.getRegion(applyTo).left + "px");
		lib.d.setStyle(loadingScreen, "width", (lib.d.getRegion(applyTo).right - lib.d.getRegion(applyTo).left) + "px");
		lib.d.setStyle(loadingScreen, "height", (lib.d.getRegion(applyTo).bottom - lib.d.getRegion(applyTo).top) + "px");
		if (applyTo.tagName.toLowerCase() == "body"){
			if ((lib.d.getRegion(applyTo).bottom - lib.d.getRegion(applyTo).top) < lib.d.getViewportHeight()){
				lib.d.setStyle(loadingScreen, "height", lib.d.getViewportHeight() + "px");
			}
		}
	}; // end position
	// 
	return publik;
}();
// class extension
YAHOO.photoViewer.DDOnTop = function(id, sGroup, config) {
    YAHOO.photoViewer.DDOnTop.superclass.constructor.apply(this, arguments);
};
YAHOO.extend(YAHOO.photoViewer.DDOnTop, YAHOO.util.DD, {
    startDrag: function(x, y) {
        var style = this.getEl().style;
        style.zIndex = YAHOO.photoViewer.zIndex++;
    },
    endDrag: function(x, y){
    	//var pos = "[" + lib.e.getPageX(x) + "," + lib.e.getPageY(x) + "]";
    	var pos = "[" + lib.d.getRegion(this.getEl()).left + "," + lib.d.getRegion(this.getEl()).top + "]"; 
		var id = this.getEl().id.split("-");
		id.splice(id.length - 1, 1);
		id = id.join("-");
		YAHOO.photoViewer.controller.getViewer(id).setProperty("xy", pos);
    }
});
// singleton objects
YAHOO.photoViewer.zIndex = 1000;
YAHOO.photoViewer.controller = function(){
	var viewers = {};
	var publik = {
		init: function(){
			for (var a in YAHOO.photoViewer.config.viewers){
				viewers[a] = new YAHOO.photoViewer.base(YAHOO.photoViewer.config.viewers[a].properties.id);
				viewers[a].init();
			}
		},
		getViewer: function(id){
			return viewers[id];
		}
	};
	// private
	//
	return publik;
}();
// load when dom loads
// DOMReady does not work when constructing the dom via script insert
//lib.e.onDOMReady(YAHOO.photoViewer.controller.init, YAHOO.photoViewer.controller, YAHOO.photoViewer.controller);