// Place your application-specific JavaScript functions and classes here
// This file is automatically included by javascript_include_tag :defaults

var Navigation = Class.create({
	options: {
		container: 'nav',
		nav: '.main',
		subnav: '.subnav',
		wrap: '.wrap',
		searchInput : "q",
		searchTrigger : "change",
		loginInput : "user_login",
		passInput : "user_password"
	},
	
	initialize: function(options){
		this.options = Object.extend(Object.clone(this.options), options);
		this.container = $(this.options.container);
		this.initializeLogin();
		this.markup();
	},
	
	initializeLogin: function(){
		this.loginEl = $(this.options.loginInput);
		this.passEl = $(this.options.passInput);
		if(this.loginEl && this.passEl){
			if(this.loginEl.getValue().empty())
				this.loginEl.addClassName('blur');
			if(this.passEl.getValue().empty())	
				this.passEl.addClassName('blur');
		}
	},
	
	markup: function(){
		this.container.childElements().invoke('addClassName', this.options.nav.replace(".", ""));
		this.container.select(this.options.subnav).each(function(ul){
			ul.wrap('div', {'class': this.options.wrap.replace(".", ""), style: 'display: none;'});
		}.bind(this));
		this.container.select(this.options.wrap).invoke('wrap', 'div', {'class': 'outer_wrap'});
		this.setupObservers();
	},
	
	setupObservers: function(){
		// Nav Hover Observers
		this.container.childElements().each(function(el){
			el.observe('mouseenter', this.handleMouseOver.bind(this));
			el.observe('mouseleave', this.handleMouseOut.bind(this));
		}.bind(this));
		this.container.select('input', 'button').each(function(input){
			input.observe('focus', this.handleFocus.bind(this));
			input.observe('blur', this.handleBlur.bind(this));
		}.bind(this));
		
		// Search Observers
		var trigger;
		if(trigger = $(this.options.searchTrigger)){
			$(trigger).observe("click", this.openAndFocus.bindAsEventListener(this, 'search-nav'));	
		}
		
		// Login Observers
		$$('.login_trigger').each(function(el){
			el.observe("click", this.openAndFocus.bindAsEventListener(this, 'user-nav'));
		}.bind(this));
	},
	
	handleFocus: function(ev){
		var el = ev.findElement();
		var navEl = el.up(this.options.nav);
		navEl.addClassName('focused');
		el.removeClassName('blur');
	},
	
	handleBlur: function(ev){
		var el = ev.findElement();
		var navEl = el.up(this.options.nav);
		
		if(this.empty(el.getValue())){
			el.clear();
			el.addClassName('blur');
		}
		
		navEl.removeClassName('focused');
		this.closeNav.bind(this).delay(0.125, navEl);
	},
	
	handleMouseOver: function(ev){
		var el = ev.findElement(this.options.nav);
		if(el.closer)
			window.clearTimeout(el.closer);
		this.openNav(el);
	},
	
	handleMouseOut: function(ev){
		var el = ev.findElement(this.options.nav);
		el.closer = this.closeNav.bind(this).delay(0.25, el);
	},
	
	openNav: function(el, options){
		el.addClassName('open');
		var wrap = el.select(this.options.wrap).first();
		var id = wrap.identify();
		if(wrap.visible())
			return;

		var defaults = 	{
			duration: 0.125,
			fps: 100,
			queue: {position: 'end', scope: id, limit: 2}
		}
		if(Prototype.Browser.IE7){
			defaults.afterFinish = function(){
				var subHeight = el.select('.subnav').first().getHeight();
				var height = el.getHeight() + subHeight;
				el.setStyle({
					height: height+"px",
					overflow: 'visible'
				});
			}
		}
		
		Effect.SlideDown(wrap, Object.extend(defaults, options));
	},
	
	closeNav: function(el, options){
		if(!el || el.hasClassName('focused'))
			return;
		
		el.removeClassName('open');
		var wrap = el.select(this.options.wrap).first();
		var id = wrap.identify();
		
		var defaults = {
			duration: .125,
			fps: 100,
			queue: {position: 'end', scope: id, limit: 2}
		}
		if(Prototype.Browser.IE7)
			defaults.afterFinish = function(){ el.writeAttribute('style', ''); }		
		
		Effect.SlideUp(wrap, Object.extend(defaults, options));
	},
	
	openAndFocus : function(ev, el){
		ev.stop();
		if(el = $(el)){
			var viewport = document.viewport.getScrollOffsets();
			if(parseInt(el.cumulativeOffset().top+el.getHeight()) < viewport.top)
				el.scrollTo();
			this.openNav(el, {
				afterFinish: function(){ el.select('input').first().focus(); }
			});
		}
	},
	
	empty: function(str){
		return ((str.match(/^\s*$/)) ? true : false);
	}
})

var Loves = Class.create({	
	initialize: function(el){
		if(this.el = $(el)){
			this.assignObserver();
		}
	},
	
	assignObserver: function(){
		this.el.observe('click', this.ajaxCall.bind(this));
	},
	
	ajaxCall: function(ev){
		el = ev.findElement('a');
		ev.stop();
		new Ajax.Request(el.href, {
			method: "get",
			onCreate: function(transport){
				el.toggleClassName('loved');
			}
		});
	}
});

var takeAction = Class.create({
	actionButton : "action",
	actionBlock : "actions_block",
	left: null,
	top: null,
	
	initialize : function(){
		$(this.actionButton).observe('click', this.toggle.bind(this));
		this.left = $(this.actionButton).viewportOffset().first();
		this.top = $(this.actionButton).viewportOffset().last();
		$(this.actionBlock).setStyle({
			position: "absolute",
			top: (this.top-10)+"px",
			left: (this.left-10)+"px"
		});
	},
	
	toggle : function(ev){
		ev.stop();
		$(this.actionBlock).toggle();
	}
});

var focusForms = Class.create({
	postfix : '_focuser',
	fields : [],
	
	initialize : function(formSelector, options){
		var cls = this;
		Object.extend(this, options);
		var theForms = $$(formSelector);
		theForms.each(function(form){
			form.select('input[type="text"], input[type="password"], textarea').each(function(field){
				cls.fields.push(field);
			});
		});
		this.assignObservers();
	},
	
	assignObservers : function(){
		var cls = this;
		this.fields.each(function(field){
			var theInput = $(field);
			
			var oldFocuser = $(theInput.identify()+cls.postfix);
			if(oldFocuser){
				oldFocuser.remove();
			}
			
			var hoverBlock = new Element('span', {
				id: theInput.identify()+cls.postfix,
				'class': 'focuser'
			}).setStyle({
				position: 'absolute',
				top: theInput.positionedOffset().top-4+"px",
				left: theInput.positionedOffset().left-4+"px",
				width: theInput.getDimensions().width+8+"px",
				height: theInput.getDimensions().height+8+"px",
				zIndex: -10,
				display: "none"
			});
			
			theInput.insert({before: hoverBlock});
			
			theInput.observe('focus', function(ev){
				cls.focusAction(ev);
			});
			theInput.observe('blur', function(ev){
				cls.blurAction(ev);
			});
		});
	},
	
	focusAction : function(ev){
		var el = ev.element();
		$(el.identify()+this.postfix).show();
	},
	
	blurAction : function(ev){
		var el = ev.element();
		$(el.identify()+this.postfix).hide();
	}
});

var optionalBlocks = Class.create({
	trigger : '.optional_trigger',
	postfix : '_trigger',
	hoverColor : '#a01d23',
	
	initialize : function(options){
		Object.extend(this, options);
		this.assignObservers();
	},
	
	assignObservers : function(){
		cls = this;
		this.triggers = $$(this.trigger);
		this.triggers.each(function(trigger){
			trigger.origColor = trigger.getStyle("color");
			
			trigger.observe('mouseover', function(){
				this.setStyle({color: cls.hoverColor});
			});
			
			trigger.observe('mouseout', function(){
				this.setStyle({color: trigger.origColor});
			});
			
			trigger.origModifyer = trigger.innerHTML.match(/show|view/i);
			trigger.origModifyer = (trigger.origModifyer ? trigger.origModifyer.first() : null);
			
			cls.contentBlock(trigger).hide();
			trigger.observe("click", function(ev){
				cls.toggle(ev, trigger);
			});			
		});
	},
	
	contentBlock : function(trigger){
		return $($(trigger).identify().replace(/_trigger/i, ""));
	},
	
	toggle : function(ev, el) {
		ev.stop();
		var blockEl = this.contentBlock(el);
		blockEl.toggle();
		el.toggleClassName('optional_trigger-on');
		if(el.origModifyer){
			if(el.innerHTML.match(/hide/i)){
				el.update(el.innerHTML.replace(/hide/i, el.origModifyer));
			}else{
				var firstModChar = el.origModifyer.charAt(0);
				var newMod = (firstModChar.match(/[A-Z]/) ? "Hide" : "hide");
				el.update(el.innerHTML.replace(el.origModifyer, newMod));
			}
		}
	}
});

var savedNotice = Class.create({
	options : {
		delay: 0.5,
		duration: 0.25,
		noticeClass: 'saved_overlay'
	},
	
	initialize : function(id, options){
		this.options = Object.extend(this.options, options);
		if(this.parentEl = $(id)){
			this.display();
		}
	},
	
	display : function(){
		var cls = this;
		var ts = new Date().getTime();
		this.notice = new Element('div', {
			'class': this.options.noticeClass,
			id: 'saved_notice_'+ts
		}).setStyle({
			display: 'none'
		}).insert("&nbsp;");
		this.parentEl.insert({bottom: this.notice});
		this.notice = $(this.notice.identify());
		
		this.notice.appear({
			duration: cls.options.duration,
			afterFinish: cls.fade.bind(cls)
		});
	},
	
	fade : function(){
		var cls = this;
		this.notice.fade({
			duration: cls.options.duration,
			delay: cls.options.delay,
			afterFinish: cls.remove.bind(cls)
		});
	},
	
	remove : function(){
		var cls = this;
		this.notice.remove();
	}
});

var Flashes = Class.create({
	container: null,
	options: {
		slideDuration: 0.125,
		bounceDuration: 0.0625,
		fps: 100
	},
	
	initialize: function(id, options){
		this.options = Object.extend(Object.clone(this.options), options);
		if(this.container = $(id)){
			this.setupClosers();
		}
	},
	
	setupClosers: function(){
		this.container.select("a.remover").each(function(a){
			this.assignAsCloser(a);
		}.bind(this));
	},
	
	assignAsCloser: function(el){
		el.observe('click', function(ev){
			ev.stop();
			this.popUp();
		}.bind(this));
	},
	
	popUp: function(opts){		
		var flash = this.container.select('.flash').first();
		flash.morph('padding-top:10px;', {
			duration: this.options.bounceDuration,
			fps: this.options.fps,
			afterFinish: function(){
				new Effect.SlideUp(this.container, Object.extend(Object.clone(opts), {
					duration: this.options.slideDuration,
					fps: this.options.fps
				}));
			}.bind(this)
		});
	},
	
	popDown: function(opts){
		var flash = this.container.select('.flash').first();
		flash.setStyle('padding-top: 10px;');
		new Effect.SlideDown(this.container, {
			duration: this.options.slideDuration,
			fps: this.options.fps,
			afterFinish: function(){
				flash.morph('padding-top: 5px;', Object.extend(Object.clone(opts), {
					duration: this.options.bounceDuration,
					fps: this.options.fps
				}));
			}.bind(this)
		});
	},
	
	build: function(content, type){
		type = type || "notice";
		var link = new Element('a', {'class': 'remover', href: '#'}).update("close");
		var flash = new Element('div', {
			'class': 'flash '+type,
			id: 'flash-'+type
		}).insert(content).insert(link);
		
		this.assignAsCloser(link);
		return flash;
	},
	
	hasFlash: function(){
		return (this.container.select('.flash').first()) ? true : false
	},
	
	replace: function(content, type){
		this.popUp({
			afterFinish: function(){
				this.insertBehind(content, type);
				this.popDown();
			}.bind(this)
		});
	},
	
	create: function(content, type){
		if(this.hasFlash() && this.container.visible()){
			this.replace(content, type);
		}else{
			this.insertBehind(content, type);
			this.popDown();
		}
	},
	
	insertBehind: function(content, type){
		this.container.hide();	
		this.container.update(this.build(content, type));
	}
});

var BatchFlash = Class.create(Flashes, {
	initialize: function($super, id, options){
		$super(id, options);
		this.options.frequency = this.options.frequency || 15; // Short-polling frequency in seconds.
		this.options.type = this.options.type || "short";
		if(this.options.pollUrl){
			if(this.options.type == "long"){
				this.longPoll();
			}else{
				this.shortPoll();
			}			
		}
	},
	
	shortPoll: function(){
		new Ajax.Request(this.options.pollUrl,
			{
				method: 'get',
				onSuccess: function(transport){
					res = transport.responseText;
					if(res.empty()){
						this.poller = this.shortPoll.bind(this).delay(this.options.frequency);
					}else{
						this.create(res, 'notice');
					}					
				}.bind(this),
				onFailure: function(transport){
					res = transport.responseText;
					if(res.empty() && this.poller){
						window.clearTimeout(this.poller);
					}else if(!res.empty()){
						this.create(res, 'error');
					}	
				}.bind(this)
			}
		);
	},
	
	longPoll: function(){
		new Ajax.Request(this.options.pollUrl,
			{
				method: 'get',
				onSuccess: function(transport){
					res = transport.responseText;
					if(res.empty()){
						this.longPoll();
					}else{
						this.create(res, 'notice');
					}					
				}.bind(this),
				onFailure: this.longPoll
			}
		);
	}
});

var HelpBugs = Class.create({
	options: {
		tagName: "rel",
		key: "?",
		url: "/help/faq/fetch.json"
	},
	
	initialize: function(options){
		this.options = Object.extend(this.options, options);
		this.buildTag();
		this.scrubPage();
		if(document.loaded){
			this.showHelpers();
		}else{
			Event.observe(window, 'load', function(){
				this.showHelpers();
			}.bind(this));
			// Event.observe(window,'unload',Event.unloadCache,false);
		}
	},
	
	buildTag: function(){
		this.tag = new Element('a', {
			'class': "help_bug lbOn",
			tabindex: '-1'
		}).update("Help");
	},
	
	scrubPage: function(){
		var reld = $$("[rel]");
		this.helpSlugs = new Array();
		reld.each(function(obj){
			var rel = obj.getAttribute("rel");
			if(!(rel.match(/^\?/))){ return; }
			var thisTag = this.tag.cloneNode(true);
			thisTag.writeAttribute({
				href: rel.replace("?", "#")
			});
			thisTag.hide();
			
			obj.insert(thisTag);
			this.helpSlugs.push(rel.replace("?", ""));
		}.bind(this));
		
		if(this.helpSlugs.length <= 0)
			return;
		
		this.queryText();
	},
	
	queryText: function(){
		var clazz = this;
		new Ajax.Request(clazz.options.url, {
			method: "get",
			parameters: {slugs: clazz.helpSlugs.join(",")},
			onSuccess: function(transport){
				clazz.helpResponse = transport.responseJSON;
				clazz.markupHelpers();
			}
		});
	},
	
	markupHelpers: function(){
		var helpBlock = new Element('div', {id: 'helpers'}).hide();
		this.helpResponse.each(function(el){
			el = el.faq || el;
			var elBlock = new Element('div', {id: el.slug});
			var excerpt = new Element('div', {'class': "excerpt"}).update(el.excerpt.unescapeHTML());
			// var body = new Element('div', {'class': "body"}).update(el.body.unescapeHTML()).hide();
			
			excerpt.insert(
				new Element('p').insert(
					new Element('a', {
						href: el.permalink
					}).update("Read more &raquo;")
				)
			);
			
			elBlock.insert(excerpt); // .insert(body);
			helpBlock.insert(elBlock);
		});
		$(document.body).insert(helpBlock);
	},
	
	showHelpers: function(){
		$$('.help_bug').invoke('appear');
	}
});

Ajax.Pagination = Class.create({
	options: {
		selector: '.mini_pagination'
	},
	
	initialize: function(options){
		this.options = Object.extend(Object.clone(this.options), options);		
		this.assignObservers();
	},
	
	assignObservers: function(){
		$$(this.options.selector+" a").each(function(a){
			a.observe('click', function(e){
				e.stop();
				el = e.findElement();
				this.startIndicator(el);
				new Ajax.Request(el.href, { method: 'get' });
			}.bind(this));
		}.bind(this));
	},
	
	startIndicator: function(el){
		var wrapper = el.up(this.options.selector);
		var current = wrapper.select('.current').first();
		current.setStyle({overflow: 'hidden'});
		current.pulsate({pulses: 10, duration: 5, from: 0.25});
	}
});

var ExternalLinks = Class.create({
	options: {
		rel: 'external',
		target: '_blank'
	},
	links: [],
	
	initialize: function(options){
		this.options = Object.extend(Object.clone(this.options), options)
		this.setupLinks();
	},
	
	setupLinks: function(){
		var links = $$('[rel]');
		var regex = new RegExp(this.options.rel, "gi");
		links.each(function(a){
			var rege
			if(a.rel.match(regex)){
				a.writeAttribute('target', this.options.target);
			}
		}.bind(this));
	}
});

var Spinner = {
	show: function(container){
		new Spinner.Overlay(container);
	},
	
	hide: function(container){
		$(container).select('.spinner_overlay').invoke('hide');
	}
}

Spinner.Overlay = Class.create({
	container: null,
	spinner: null,
	
	initialize: function(container){
		if(this.container = $(container)){
			this.build();
		}
	},
	
	build: function(){
		var spinnerId = this.container.identify()+"_spinner";
		if(this.spinner = $(spinnerId)){
			this.spinner.show();
		}else{
			this.spinner = new Element('p', {
				id: spinnerId,
				'class': "spinner_overlay"
			}).update("Loading...");
			this.container.insert(this.spinner);
		}
	}
});

var focusableForms;

document.observe('dom:loaded', function(){
	Prototype.Browser.IE7 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5)) == 7;
	new Navigation();
	focusableForms = new focusForms('.styled');
	new optionalBlocks();
	new Ajax.Pagination();
	new Flashes('flash-tray');
	new ExternalLinks();
});

function confirm_destroy(element, action, remote, remote_opts) {
	var remote;
	remote = remote ? remote : false;
	if (confirm("Are you sure?")) {
		var f = new Element('form', {'method': 'post', 'action': action}).setStyle({display: 'none'}).insert(
			new Element('input', {'type': 'hidden', 'name': '_method', 'value': 'delete'})
		);
		element.up().insert(f);
		
		if(remote){
			opts = Object.extend({asynchronous:true, evalScripts:true, parameters:Form.serialize(f)}, remote_opts);
			new Ajax.Request(action, opts);
		}else{
			f.submit();
		}		
	}
	return false;
}

function toggleDiscussion(el){
	var el = $(el);
	var elButton = el.select('a.disabler').first();
	
	el.toggleClassName('disabled_discussion');
	
	if(el.hasClassName('disabled_discussion')){
		elButton.update("enable");
	}else{
		elButton.update("disable");
	}
}

function removeOverlay(){
	$$('.overlay').invoke('remove');
}
