var messageStack = stdClass.extend({
	//constructor
	constructor: function(el, settings) {
		this.base();
		// initialize settings
		Object.extend(this.s, {
			timer: null,
			waitTime: 4000,
			effectTime: 2000,
			closeSelector: ".close"
			/* put extensions to collections here */
		});
		
		// initialize nodes
		Object.extend(this.n, {
			el: el,
			childEl: [],
			tempContainer: document.createElement('div')
			/* put extensions to nodes here */
		});
		
		// initialize collections
		Object.extend(this.c, {
			messageFunctions: {
				success: this.successMessage.bind(this),
				error: this.errorMessage.bind(this)
			}
			/* put extensions to collections here */
		});
		var eles = this.n.el.getElementsBySelector('ul');
		
		for(var x=0; x<eles.length; x++){
			var childEl = {
				el: eles[x],
				timer: null
			}
			this.startTimer(childEl);
			this._attachEvents(childEl);
		}
	},
	closeClicked: function(childEl){
		this.removeMessage(childEl);
	},
	addMessage: function(message, type){
		if(!this.n.el){
			return;
		}
		if(typeof(this.c.messageFunctions[type]) == "function"){
			var html = this.c.messageFunctions[type](message);
		}else{
			return;
		}
		
		this.n.tempContainer.innerHTML = html;
		var childEl = {
			el:this.n.tempContainer.firstChild,
			timer:null
		}
		this.n.el.appendChild(childEl.el);
		this._attachEvents(childEl);
		Element.show(this.n.el);
		if(window.Effect){
			Effect.BlindDown(childEl.el,{
				duration: (this.s.effectTime/1000),
				afterFinishInternal: function(effect) {
					effect.element.undoClipping();
					effect.element.style.height = '';
				}
			});
		}else{
			Element.show(childEl.el);
		}
		this.startTimer(childEl);
	},
	removeMessage: function(childEl) {
		this.endTimer(childEl);
		if(window.Effect){
			Effect.Fade(childEl.el, {
				duration: (this.s.effectTime/1000)
			});
			/*Effect.BlindUp(childEl.el,{
				duration: (this.s.effectTime/1000),
				afterFinishInternal: function(effect) {
					effect.element.undoClipping();
					effect.element.style.height = '';
					Element.hide(effect.element);
				}
			});*/
		}else{
			Element.hide(this.n.el);
		}
	},
	startTimer: function(childEl) {
		this.endTimer(childEl);
		this.s.timer = setTimeout(this.removeMessage.bind(this, childEl), this.s.waitTime);
	},
	endTimer: function(childEl) {
		if(childEl.timer != null){
			clearTimeout(childEl.timer);
			childEl.timer = null;
		}
	},
	successMessage: function(message){
		var html = '<ul class="success">';
		html += '<li class="title">Success</li>';
		html += '<li>' + message + '</li>';
		html += '</ul>';
		return html;
	},
	errorMessage: function(message){
		var html = '<ul class="error">';
		html += '<li class="title">Error</li>';
		html += '<li>' + message + '</li>';
		html += '<li class="close">Close me</li>';
		html += '</ul>';
		return html;
	},
	_attachEvents: function(childEl) {
		var eles = document.getElementsBySelector(this.s.closeSelector, (childEl.el||this.n.el));
		for(var x=0; x<eles.length; x++){
			this.eObserve(eles[x], 'click', this.closeClicked.bind(this, childEl));
		}
	}
});
Behaviour.register({
	'div#messagestack' : function(el){
		new messageStack (el);
	}
});EventSelectors.register({
	'div#DiscussionFilters a:click': function(el, e) {
		var ele = document.getElementsBySelector("div.tabs li.active a");
		if(ele && ele.length > 0){
			if(el.href.indexOf("/discussions/?") != -1){
				window.location = ele[0].href + "?" + el.href.substr(el.href.indexOf("?")+1);
				Event.stop(e);
			}
		}
	}
}, true);/**
 * MasterTabModule
 * Kramer 070313
 *
 * AJAJ tab manager
 **/
var MasterTabModule = stdClass.extend({
	// Static properties

	settings: function(settings) {
		if (typeof(this.s) == 'undefined') {
			this.base();
			this.n.tabs = [];
			this.n.content = null;
			this.activeTab = null;
			this.getData = [];

			Object.extendProperties(this.s, {
				container: null,
				tabsULContainerSelector: '.tabs',
				contentNodeSelector: '.tab_content',
				activeTabClass: 'active',
				loadingTabClass: 'loading',
				ajajParams: ['__json=MasterTabModule'],                                                               // An array of "var=val" settings to be used as request variables in AJAJ calls
				passThroughGETVars: [new RegExp('.*')],                                                               // GET variables which are used on the current page, which we should pass through to the AJAJ request. A list of regular expressions, so ".*" matches all get vars.
				showErrors: true,
				showDebugs: ['kramer'],
				cache: true,                                                                                          // Cache data after retrieving it once? Should be TRUE for optimization's sake, unless there's some reason you want to hammer the server.
				cachePreLoadedContent: false                                                                           // Should we save the content of the tab which is opened at page load, rather than AJAJing it? A minor optimization.
				// Adam turned the above to false to make things work when the starting tab has changing content (in this case, it was in the messages)
			});
			Object.extendProperties(this.s, settings);
		}
	},

	constructor: function(settings) {
		this.settings(settings);
		
		var ele = document.getElementsBySelector('.tabs', this.s.container);
		Element.parseClasses(ele[0]);
		if(ele[0].vars){
			this.s.ajajParams.push('__pmid='+ele[0].vars.pmid);
		}
		
		this.acquireNodes();
		this.getGetData();
	},

	acquireNodes: function() {
		this.n.content = document.getElementsBySelector(this.s.contentNodeSelector, this.s.container)[0]; // Grab the content container
		var tabsULContainer = document.getElementsBySelector(this.s.tabsULContainerSelector, this.s.container)[0];           // Look inside for .tabs
		var tabs = tabsULContainer.getElementsByTagName('li');        // Grab LIs
		for (var x=0; x<tabs.length; x++) {
			var tab = {
				node: tabs[x],
				event: null,
				cachedData: null,
				href: tabs[x].getElementsByTagName('a')[0].getAttribute('href'),
				pmid: DOM.getClassData('pmid', tabs[x])
			};
			if (Element.hasClassName(tabs[x], this.s.activeTabClass)) {
				this.activeTab = tab;
				if (this.s.cachePreLoadedContent) tab.cachedData = this.n.content.innerHTML;
			}
			this.n.tabs.push(tab);
		}
		this.activateEvents();
	},

	activateEvents: function() {
		for (var x=0; x<this.n.tabs.length; x++) {
			this.n.tabs[x].event = this.eObserve(this.n.tabs[x].node, 'click', this.onTabClick.bind(this, this.n.tabs[x]));
		}
	},

	onTabClick: function(whichTab, e) {
		Event.stop(e);
		Effect.Throb(this.n.content);
		Element.addClassName(whichTab.node, this.s.loadingTabClass);
		if (whichTab.cachedData && this.s.cache) {
			this.activateTab(whichTab);
		} else {
			this.ajajOut(whichTab);
		}
	},

	getGetData: function() {
		this.getData = [];
		var getvars = document.location.search.substring(1).split('&');
		for (var x=0; x<getvars.length; x++) {
			var getvar = getvars[x].split('=');
			for (var y=0; y<this.s.passThroughGETVars.length; y++) {
				if (getvar[0].match(this.s.passThroughGETVars[y])) {
					this.getData.push(getvars[x]);
				}
			}
		}
	},

	ajajOut: function(whichTab) {
		if (whichTab.href) {
			var ajaj = Object.toJSON({
				"ver": "0.1",
				"meta": {},
				"data": null,
				"requests": [
					{
						id: 0,
						type: "getPageModule",
						data: {
							href: whichTab.href
						}
					}
				]
			});
			var url = whichTab.href;
			var postData = [];                                                                                      // Posted via POST
			for (var x=0; x<this.s.ajajParams.length; x++) {
				postData.push(this.s.ajajParams[x]);
			}

			// Add in the pass-through GET vars...
			url += (this.getData[0]) ? '?'+this.getData.join('&') : '';

			// Add on the JSON data...
			postData.push('data='+ajaj);
			postData = postData.join('&');
			this.debug('AJAJ out to:\n'+url+'\nwith post data:\n'+postData);

			new Ajax.Request(url, {
				method: 'post',
				parameters: postData,
				onSuccess: this.ajajIn.bind(this, whichTab),
				onFailure: this.ajajFail.bind(this, whichTab)
			});
			return true;
		} else {
			Element.removeClassName(whichTab.node, this.s.loadingTabClass);
			this.error('This tab has no discernable href designated in the tab link.');
			return false;
		}
	},

	ajajIn: function(whichTab, ret) {
		this.debug('AJAJ in:\n\n'+ret.responseText);
		var object = ret.responseText.evalJSON();
		if (object.meta.success) {
			whichTab.cachedData = object.responses[0].data;
			this.activateTab(whichTab);
		} else {
			this.error('Server interaction failure: "'+object.meta.error+'"');
			return false;
		}
	},

	ajajFail: function(whichTab, ret) {
		this.error('Error fetching content for PMID#'+whichTab.pmid);
	},

	activateTab: function(whichTab) {
		if (this.activeTab) Element.removeClassName(this.activeTab.node, this.s.activeTabClass);
		this.activeTab = whichTab;
		Element.removeClassName(whichTab.node, this.s.loadingTabClass);
		Element.addClassName(this.activeTab.node, this.s.activeTabClass);

		this.setContent(whichTab.cachedData);
		Effect.CancelThrob(this.n.content);
	},

	setContent: function(html) {
		this.n.content.innerHTML = html;
		EventSelectors.apply();
		//do_sifr();
	},

	error: function(text) {
		this.shout('MasterTabModule Error: '+text, this.s.showErrors);
	},

	debug: function(text) {
		this.shout('MasterTabModule Debug: '+text, this.s.showDebugs);
	},

	shout: function(text, toWhom) {
		if (toWhom === true) { // true == everybody
			alert(text);
		} else if (toWhom instanceof Array) {
			for (var x=0; x<toWhom.length; x++) {
				shout(text, toWhom[x]);
			}
		}
	}
});
EventSelectors.register({
	'div.tabs': function(node) {
		// Yes, the selector above should be 'div.box.tabs', but the
		// EventSelectors selector parser doesn't handle multiple classes.
		if (Element.hasClassName(node, 'box')) {
			new MasterTabModule({
				container: node
			});
		}
	}
});if(!Effect){
	var Effect = {
	};
}

Object.extend(Effect, {
	throbbers: [],
	Throb: function(node){
		var throbber = {
			node: node,
			key: 'throbber',
			throbber: document.createElement('div')
		}
		Element.addClassName(throbber.throbber, "throbber");
		throbber.node.parentNode.insertBefore(throbber.throbber, throbber.node);
		
		var dims = Element.getDimensions(throbber.node);
		
		/* Add essential styles to container and throbber */
		Object.extend(throbber.throbber.style, {
			position: "absolute",
			width: dims['width']+"px",
			height: dims['height']+"px"
		});
		
		if(document.all){
			throbber.iframe = document.createElement('iframe');
			Element.addClassName(throbber.iframe, "iFrame");
			Object.extend(throbber.iframe.style, {
				position: "absolute",
				width: dims['width']+"px",
				height: dims['height']+"px",
				filter: "alpha(opacity=0)",
				opacity: "0",
				zIndex: "2"
			});
			if(parseInt(throbber.node.style.zIndex) > 1){
				Object.extend(throbber.iframe.style, {
					zIndex: parseInt(throbber.node.style.zIndex)+1
				});
			}
			throbber.throbber.appendChild(throbber.iframe);
		}
		
		Effect.throbbers.push(throbber);
	},
	CancelThrob: function(node){
		var throbber = null;
		for(var x=0; x<Effect.throbbers.length; x++){
			if(Effect.throbbers[x].node == node){
				throbber = Effect.throbbers.splice(x, 1);
				break;
			}
		}
		if(!throbber){
			return;
		}
		throbber = throbber[0];
		throbber.throbber.parentNode.removeChild(throbber.throbber);
	}
});

