
/*****************************************************************************
Micasa Packages
*****************************************************************************/
var yahoo = YAHOO; // lazy alias to YAHOO
var micasa = yahoo.namespace('micasa');

yahoo.namespace('micasa.lang'); // package for common javascript utility functions; dependent only on YUI
// yahoo.namespace('micasa.util'); // package for micasa-specific utility classes & functions; dependent on micasa.lang
yahoo.namespace('micasa.base');  // package for micasa-specific base classes; dependent on micasa.lang and micasa.util
// yahoo.namespace('micasa.shell'); // package for shell classes & functions; dependent on micasa.base
yahoo.namespace('micasa.modules'); // package for micasa-specific modules


/*****************************************************************************
Micasa Aliases
*****************************************************************************/

// micasa.xml = null; // aliased to micasa.lang.xml;
micasa.ajax = null; // aliased to micasa.lang.ajax;
micasa.cookie = null; // aliased to micasa.lang.cookie;



/*****************************************************************************
Micasa Singletons
*****************************************************************************/

micasa.session = null; // instance of micasa.base.Session;



/*****************************************************************************
Global Functions
*****************************************************************************/

$_ = function(id) {
	return document.getElementById(id);
}



/*****************************************************************************
Micasa Lang Functions
*****************************************************************************/

micasa.lang.ajax = new function() {

	this.send = function(uri, callback, data) { // wrapper to yahoo.util.Connect.asyncRequest

		/********** callback options:
		success:functionName,
		failure:functionName,
		upload:functionName,
		argument: [argument1, argument2, ...],
		scope: AjaxObject,
		timeout: 5000
		*****************************/

		if(uri) { // only URI is required
			if(yahoo.lang.isString(data)) {
				var method = 'POST';
			} else {
				var method = 'GET';
			}
			if(yahoo.lang.isFunction(callback)) {
				var doCallback = {success:callback, failure:callback};
			} else {
				var doCallback = callback;
			}
			return YAHOO.util.Connect.asyncRequest(method, uri, doCallback, data);
		}

	}

	this.setForm = function(form, optional) { // wrapper to yahoo.util.Connect.setForm
		return YAHOO.util.Connect.setForm(form, optional);
	}

	// This is the Safari/yui hack to prevent a memory leak in the default (polling) XHR response checking in yui 2.2.1
	this.safariHack = function() {
		yahoo.util.Connect.handleReadyState = function(o, callback) {
			var oConn = this;
			o.conn.onreadystatechange = function() {
				if (o.conn.readyState == 4) {
					oConn.handleTransactionResponse(o, callback);
				}
			};
		}
	}

}
micasa.ajax = micasa.lang.ajax; // alias

micasa.lang.browser = new function() {

	this.isSafari = function() {
		return (navigator.userAgent.toLowerCase().indexOf('safari') > 0);
	}

	this.isMSIE = function() {
		return (navigator.appName == 'Microsoft Internet Explorer');
	}

	this.isOpera = function() {
		return (navigator.appName == 'Opera');
	}

}

micasa.lang.cookie = new function() {

	this.get = function(name) {
		if(document.cookie.length > 0) {
			var start = document.cookie.indexOf(name+'=');
			if(start != -1) {
				start = start+name.length+1;
				var end = document.cookie.indexOf(';',start);
			    if(end == -1) end = document.cookie.length;
	    		return unescape(document.cookie.substring(start,end));
			}
		}
		return null;
	}

	this.set = function(name, value, expires, path, domain, secure) {
	    var newCookie = name + '=' + escape(value) + ((expires) ? '; expires=' + expires.toGMTString() : '') + ((path) ? '; path=' + path : '') + ((domain) ? '; domain=' + domain : '') + ((secure) ? '; secure' : '');
	    document.cookie = newCookie;
	}

}
micasa.cookie = micasa.lang.cookie; // alias

micasa.lang.dom = new function() {
	
	this.classNameHack = function() {

		// YAHOO.util.Dom.getElementsByClassName('class-name', 'tag', rootElement)
		yahoo.util.Dom.getElementsByClassName = function(searchClass, tag, node) {
			node = YAHOO.lang.isString(node) ? $_(node) : node; // this allows node to be a divId or a div
			var classElements = new Array();
			if(node == null) node = document;
			if(tag == null) tag = '*';
			var els = node.getElementsByTagName(tag);
			var elsLen = els.length;
			var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
			for (i = 0, j = 0; i < elsLen; i++) {
				if ( pattern.test(els[i].className) ) {
					classElements[j] = els[i];
					j++;
				}
			}
			return classElements;

		}
		
	}
	
}	

micasa.lang.getParam = function(name, url) {
	if(!url) query = window.location.search.substring(1);
	else query = url.substring(url.indexOf('?')+1);
	var vars = query.split('&');
	for(var i=0; i<vars.length; i++) {
		var pair = vars[i].split('=');
		if(pair[0] == name) {
			return pair[1];
		}
	}
}






/*****************************************************************************
Micasa Base Session Class
*****************************************************************************/

micasa.base.Session = function() {
	
	this.layout = null;
	this.galleries = new Array(); // used to store the data for the galleries that have been loaded this session. different from layout.modules.galleries which is the gallery modules on the page.
	
	// init the session when the dom is ready
	yahoo.util.Event.onDOMReady(function() {
		this.init();
	}, this, true);
	
	this.init = function() {

		// This is the Safari/yui hack to use a custom getElementsByClassName function; for now we're using it for all browsers although Safari may be the only browser that needs it
		micasa.lang.dom.classNameHack();

		// This is the Safari/yui hack to prevent a memory leak in the default (polling) XHR response checking in yui 2.2.1
		if(micasa.lang.browser.isSafari()) {
			micasa.ajax.safariHack();
		}

		this.layout = new micasa.base.Layout();
		this.layout.init();

	}

	this.lookupGallery = function(id) {
		if(this.galleries[id]) {
			return this.galleries[id];
		} else {
			return false;
		}
	}
	
	this.addGallery = function(gallery) {
		this.galleries[gallery.id] = gallery;
	}

}
micasa.session = new micasa.base.Session();



/*****************************************************************************
Micasa Base Layout Class
*****************************************************************************/

micasa.base.Layout = function() {
	
	this.masterDiv = null;
	this.modules = function(){};
	this.modules.galleries = new Array();
	this.modules.features = new Array();
	
	this.init = function() {
		
		this.masterDiv = $_('masterDiv');
		this.modules.loadPhotoGalleries();
		this.modules.loadFeatures();

	}

	this.modules.loadPhotoGalleries = function() {
		
		var galleries = YAHOO.util.Dom.getElementsByClassName('photos', 'div', this.masterDiv);
		for(var i=0; i < galleries.length; i++) {
			this.galleries[i] = new micasa.modules.PhotoGallery().init(galleries[i]);
		}
		
	}
	
	this.modules.loadFeatures = function() {
		
		var features = YAHOO.util.Dom.getElementsByClassName('unique_features', 'div', this.masterDiv);
		for(var i=0; i < features.length; i++) {
			this.features[i] = new micasa.modules.Feature().init(features[i]);
		}

	}

}


/*****************************************************************************
Micasa Data Gallery module
*****************************************************************************/

micasa.base.PhotoGallery = function() {

	this.id = null;
	this.label = null;
	this.title = null;
	this.photos = new Array();
	this.isLoaded = null;

	this.init = function() {
		this.onIsLoaded = new YAHOO.util.CustomEvent('onIsLoaded', this);
	}
	
	this.fetch = function(id) {
		this.id = id;
		var url = '/gallery?id='+this.id;
		micasa.ajax.send(url, {success:this.success, failure:this.failed, scope:this, timeout:10000});
	}
	
	this.failed = function(ajax) {
		console.log('gallery fetch failed: '+this.id);
	}
	
	this.success = function(ajax) {
		this.load(ajax.responseText);
		this.onIsLoaded.fire();
	}

	this.load = function(rawData) {
		var data = rawData.split('~');
		this.label = data[1];
		this.title = data[2];
		this.loadData(data[3]);
	}

	this.loadData = function(data) {
		var urls = data.split(',');
		for(var i=0; i < urls.length; i++) {
			this.photos[i] = new this.Photo().init(urls[i]);
		}
	}
	
	this.Photo = function() {
		
		this.src = null;
		this.image = new Image();

		this.init = function(src) {
			this.src = src;
			return this;
		}

		this.loadPhoto = function() {
			if(!this.image.src) {
				this.image.src = this.src;
			}
		}

		this.getHTML = function() {
			var html =  '';
			html = '<img src="'+this.image.src+'" width="'+this.image.width+'" height="'+this.image.height+'" alt="Click to see the next photo." title="Click to see the next photo." />';
			return html;
		}
		
	}

}



/*****************************************************************************
Micasa Photo Gallery module
*****************************************************************************/

micasa.modules.PhotoGallery = function() {
	
	this.div = null;
	this.titleSpan = null;
	this.linkToPhotoSpan = null;
	this.prevDiv = null;
	this.nextDiv = null;
	this.counterDiv = null;
	this.selectorDiv = null;
	this.onchangeEvent = null;
	this.photoDiv = null;
	this.spinnerDiv = null;
	this.counter = 1;
	this.gallery = null;
	
	this.init = function(div) {

		this.div = div;
		
		this.loadElements();
		this.setCounter();
		this.loadGallery();

		this.loadPrevPhoto();
		this.loadNextPhoto();

		this.addActions();

		return this;
		
	}

	this.loadElements = function() {
		this.titleSpan = YAHOO.util.Dom.getElementsByClassName('title', 'span', this.div)[0];
		this.linkToPhotoSpan = YAHOO.util.Dom.getElementsByClassName('linkToPhoto', 'span', this.div)[0];
		this.prevDiv = YAHOO.util.Dom.getElementsByClassName('prev', 'div', this.div)[0];
		this.nextDiv = YAHOO.util.Dom.getElementsByClassName('next', 'div', this.div)[0];
		this.counterDiv = YAHOO.util.Dom.getElementsByClassName('count', 'div', this.div)[0];
		this.selectorDiv = YAHOO.util.Dom.getElementsByClassName('selector', 'div', this.div)[0];
		this.onchangeEvent = YAHOO.util.Dom.getElementsByClassName('onchangeEvent', 'div', this.div)[0].innerHTML;
		
		this.spinnerDiv = this.div.nextSibling;
		this.photoDiv = this.div.nextSibling.nextSibling;
	}

	this.setCounter = function() {
		var counterDiv = YAHOO.util.Dom.getElementsByClassName('counter', 'div', this.photoDiv);
		if(counterDiv && counterDiv.length > 0) {
			this.counter = counterDiv[0].innerHTML*1;
		}
	}		

	this.addActions = function() {
		YAHOO.util.Event.addListener(this.prevDiv, 'click', this.prevClick, this, true);
		YAHOO.util.Event.addListener(this.nextDiv, 'click', this.nextClick, this, true);
		YAHOO.util.Event.addListener(this.photoDiv, 'click', this.nextClick, this, true);
		YAHOO.util.Event.addListener(this.selectorDiv.getElementsByTagName('select')[0], 'change', this.selectChange, this, false);
	}

	this.prevClick = function() {
		this.updateCount(-1);
		this.showPhoto();
		this.loadPrevPhoto();
		this.updateLinkToPhoto();
	}

	this.nextClick = function() {
		this.updateCount(1);
		this.showPhoto();
		this.loadNextPhoto();
		this.updateLinkToPhoto();
	}

	this.updateLinkToPhoto = function(setCount) {

		var anchor = this.linkToPhotoSpan.getElementsByTagName('a')[0];
		var url = anchor.href;
		var gallery = micasa.lang.getParam('photoGalleryModule', url);
		var counter = micasa.lang.getParam('photoGalleryCounter', url);
		this.counter = setCount ? setCount : this.counter;

		if(gallery) {
			url = url.replace('photoGalleryModule='+gallery, 'photoGalleryModule='+this.gallery.id);
		} else {
			url += url.indexOf('?') > 0 ? '&' : '?';
			url += 'photoGalleryModule='+this.gallery.id;
		}

		if(counter) {
			url = url.replace('photoGalleryCounter='+counter, 'photoGalleryCounter='+this.counter);
		} else {
			url += url.indexOf('?') > 0 ? '&' : '?';
			url += 'photoGalleryCounter='+this.counter;
		}

		anchor.href = url;

	}

	this.changeGallery = function(type, args, moduleGallery) {
		// this=data gallery
		moduleGallery.render();
	}
	
	this.toggleSpinner = function(mode) {
		if(mode == 'on') {
			this.spinnerDiv.style.display = 'block';
		} else if(mode == 'off') {
			this.spinnerDiv.style.display = 'none';
		} else if(this.spinnerDiv.style.display == 'block') {
			this.spinnerDiv.style.display = 'none';
		} else {
			this.spinnerDiv.style.display = 'block';
		}
	}

	this.render = function() {
		this.toggleSpinner('on');
		this.updateTitle();
		this.counter = 1;
		this.updateCounterText();
		this.updateLinkToPhoto();
		this.loadThisPhoto();
		this.loadNextPhoto();
		this.loadPrevPhoto();
		this.showFirstPhoto(0);
	}

	this.reload = function() {
		this.toggleSpinner('on');
		console.log
	}

	this.showFirstPhoto = function(retries) {
		var photo = this.gallery.photos[this.counter-1];
		if(retries < 100 && (photo.image.width == 0 || photo.image.height == 0)) {
			retries++;
			photoGalleryModule = this;
			setTimeout('photoGalleryModule.showFirstPhoto('+retries+');', 100); // 100 tries at 100 millisecond intervals = 10 seconds of trying
		} else if(retries == 100) {
			this.toggleSpinner('off');
			this.noPhoto();
		} else {
			this.showPhoto();
			this.toggleSpinner('off');
		}
	}
	
	this.selectChange = function(e, obj) {
		// this=<select>; obj=photo gallery module
		var id = this.options[this.selectedIndex].value;
		if(obj.onchangeEvent == 'reload') {
			obj.gallery.id = id;
			obj.updateLinkToPhoto(1);
			if(obj.linkToPhotoSpan && obj.linkToPhotoSpan.getElementsByTagName('a')[0] && obj.linkToPhotoSpan.getElementsByTagName('a')[0].href) {
				location.href = obj.linkToPhotoSpan.getElementsByTagName('a')[0].href;
			} else {
				alert('An unknown error has occurred (#201). Please reload this page and try again. Sorry for the inconvenience.');
			}
		} else if(obj.onchangeEvent == 'render') {
			if(obj.gallery.id != id) {
				var gallery = micasa.session.lookupGallery(id);
				if(gallery) {
					obj.gallery = gallery;
					obj.render();
				} else {
					obj.gallery = new micasa.base.PhotoGallery();
					obj.gallery.init();
					obj.gallery.onIsLoaded.subscribe(obj.changeGallery, obj);
					obj.gallery.fetch(id);
					micasa.session.addGallery(obj.gallery);
				}
			} else {
				alert('An unknown error has occurred (#202). Please reload this page and try again. Sorry for the inconvenience.');
			}
		} else {
			alert('An unknown error has occurred (#203). Please reload this page and try again. Sorry for the inconvenience.');
		}
	}

	this.updateCount = function(delta) {
		this.updateCounter(delta);
		this.updateCounterText();
	}
	
	this.updateCounter = function(delta) {
		this.counter += delta;
		if(this.counter < 1) {
			this.counter = this.gallery.photos.length;
		} else if(this.counter > this.gallery.photos.length) {
			this.counter = 1;
		}
	}

	this.updateCounterText = function() {
		this.counterDiv.innerHTML = this.counter + ' of ' + this.gallery.photos.length;
	}
	
	this.loadGallery = function() {
		var galleryIdDiv = YAHOO.util.Dom.getElementsByClassName('galleryId', 'div', this.photoDiv);
		var dataDiv = YAHOO.util.Dom.getElementsByClassName('data', 'div', this.photoDiv);
		var labelDiv = YAHOO.util.Dom.getElementsByClassName('label', 'div', this.photoDiv);
		if(galleryIdDiv && galleryIdDiv.length > 0 && galleryIdDiv[0].innerHTML && dataDiv && dataDiv.length > 0 && dataDiv[0].innerHTML && labelDiv && labelDiv.length > 0 && labelDiv[0].innerHTML) {
			var galleryId = galleryIdDiv[0].innerHTML;
			this.gallery = micasa.session.lookupGallery(galleryId);
			if(!this.gallery) {
				this.gallery = new micasa.base.PhotoGallery();
				this.gallery.id = galleryId;
				this.gallery.label = labelDiv[0].innerHTML;
				this.gallery.title = this.titleSpan.innerHTML;
				this.gallery.loadData(dataDiv[0].innerHTML);
				micasa.session.addGallery(this.gallery);
			}
		}
	}

	this.showPhoto = function() {
		this.photoDiv.innerHTML = this.gallery.photos[this.counter-1].getHTML();
	}

	this.noPhoto = function() {
		this.photoDiv.innerHTML = '<div class="nophoto">An error has occurred: No photo was found. Please select a different gallery.</div>';
	}

	this.loadThisPhoto = function() {
		if(this.counter-1 >= 0) {
			this.gallery.photos[this.counter-1].loadPhoto();
		} else {
			this.gallery.photos[this.gallery.photos.length-1].loadPhoto();
		}
	}

	this.loadNextPhoto = function() {
		if(this.counter < this.gallery.photos.length) {
			this.gallery.photos[this.counter].loadPhoto();
		} else {
			this.gallery.photos[0].loadPhoto();
		}
	}
	
	this.loadPrevPhoto = function() {
		if(this.counter-2 >= 0) {
			this.gallery.photos[this.counter-2].loadPhoto();
		} else {
			this.gallery.photos[this.gallery.photos.length-1].loadPhoto();
		}
	}
	
	this.updateTitle = function() {
		this.titleSpan.innerHTML = this.gallery.title;
	}	
	
}



	
/*****************************************************************************
Micasa Features module
*****************************************************************************/

micasa.modules.Feature = function() {
	
	
	this.div = null;
	this.prevDiv = null;
	this.nextDiv = null;
	this.counter = 1;
	this.maxNumFeatures = 1;
	this.spinnerDiv = null;
	this.featureDiv = null;
	this.features = new Array();
	
	this.init = function(div) {

		this.div = div;
		
		this.setCounter();
		this.loadElements();
		this.addActions();

		return this;
		
	}

	this.loadElements = function() {
		this.prevDiv = YAHOO.util.Dom.getElementsByClassName('prevDiv', 'div', this.div)[0];
		this.nextDiv = YAHOO.util.Dom.getElementsByClassName('nextDiv', 'div', this.div)[0];
		this.spinnerDiv = YAHOO.util.Dom.getElementsByClassName('featurespinner', 'div', this.div)[0];
		this.featureDiv = YAHOO.util.Dom.getElementsByClassName('featureDiv', 'div', this.div)[0];
		this.load(this.featureDiv.innerHTML);
	}

	this.setCounter = function() {
		var counterDiv = YAHOO.util.Dom.getElementsByClassName('counterDiv', 'div', this.div);
		if(counterDiv && counterDiv.length > 0) {
			this.counter = counterDiv[0].innerHTML*1;
		}
		var maxNumDiv = YAHOO.util.Dom.getElementsByClassName('maxNumDiv', 'div', this.div);
		if(maxNumDiv && maxNumDiv.length > 0) {
			this.maxNumFeatures = maxNumDiv[0].innerHTML*1;
		}
	}		

	this.addActions = function() {
		YAHOO.util.Event.addListener(this.prevDiv, 'click', this.prevClick, this, true);
		YAHOO.util.Event.addListener(this.nextDiv, 'click', this.nextClick, this, true);
	}

	this.prevClick = function() {
		this.updateCount(-1);
		this.render(false);
	}

	this.nextClick = function() {
		this.updateCount(1);
		this.render(false);
	}

	this.toggleSpinner = function(mode) {
		if(mode == 'on') {
			this.spinnerDiv.style.display = 'block';
		} else if(mode == 'off') {
			this.spinnerDiv.style.display = 'none';
		} else if(this.spinnerDiv.style.display == 'block') {
			this.spinnerDiv.style.display = 'none';
		} else {
			this.spinnerDiv.style.display = 'block';
		}
	}

	this.updateCount = function(delta) {
		this.counter += delta;
		if(this.counter < 1) {
			this.counter = this.maxNumFeatures;
		} else if(this.counter > this.maxNumFeatures) {
			this.counter = 1;
		}
	}

	this.render = function(noFetch) {
		if(this.features[this.counter-1]) {
			this.featureDiv.innerHTML = this.features[this.counter-1];
		} else if(!noFetch) {
			this.fetch(this.counter-1);
		}
	}
	
	this.fetch = function(id) {
		// this.toggleSpinner('on');
		var url = '/feature?id='+id;
		micasa.ajax.send(url, {success:this.success, failure:this.failed, scope:this, timeout:10000});
	}
	
	this.failed = function(ajax) {
		// this.toggleSpinner('off');
		console.log('feature fetch failed: '+this.counter-1);
	}
	
	this.success = function(ajax) {
		// this.toggleSpinner('off');
		this.load(ajax.responseText);
		this.render(true);
	}

	this.load = function(featureHTML) {
		this.features[this.counter-1] = featureHTML;
	}
		


}
	


	


	


	


	


	


	


	


	


	


	


	


	

