
window.chatbox = function(box, sendform, startform, endform) {
	var wait_before_connecting = 5, userid = false, connected = false, listenurl, listening_request = false;
	startform.erase("disabled"); //just in case
	
	//effects galore!
	endform.effect = new Fx.Tween(endform, {property:"right", unit:"%", link:"chain", duration:300});
	var nav = document.getElement("ul.navigation");
	nav.effect=new Fx.Morph(nav, {unit:"%"});
	endform.appear = function() {
		endform.getElement("[type=submit]").erase("disabled").removeClass("hidden");
		endform.effect.start(100,0);
		nav.effect.start({opacity: [1, 0], width:[100, 80]});
	};
	endform.disappear = function() {
		endform.getElement("[type=submit]").set("disabled", "disabled");
		endform.effect.start(0,100);
		nav.effect.start({opacity: [0, 1], width:[80, 100]});
	};
	
	startform.effect =new Fx.Reveal(startform, {link:"chain"}).addEvents({
		hide:function(){startform.atthetop=true;},
		start:function(){
			if (startform.atthetop) {
				box.grab(startform);
				startform.atthetop=false;
			}
		},
		show:function(){box.scroll.toBottom();}
	});
	startform.appear = function() {
		startform.getElement("[type=submit]").erase("disabled");
		startform.effect.reveal();
	};
	startform.disappear = function() {
		startform.getElement("[type=submit]").set("disabled", "disabled");
		startform.effect.dissolve();
	};
	
	function eraseconversation(ul) {
		ul.addClass("oldconversation").removeClass("conversation");
			new Fx.Reveal(ul).addEvent("complete", function() {
				ul.destroy();
		}).dissolve();
	}
	
	var register = (function(){
		var reg = box.getElement('div.register');
		var form = reg.getElement('form[name=register]');
		var toggle = new Fx.Reveal(reg).addEvents({
			start: function(){
				reg.removeClass('hidden');
			}
		});
		
		form.addEvent('submit', function(ev){
			ev.stop();
			reg.addClass('loading');
			async.request(this, {
				success: function(body, status) {
					reg.removeClass('loading');
					reg.empty().set('text', body); //assuming response was text/plain
						try { refreshLogin(); } catch(e){}
						toggle.dissolve();
						addmessage('usernotice', body);
				},
				error:function(b, status){
					reg.removeClass('loading');
					reg.getElement('.error').removeClass('hidden').set('text', (status>=500) ? "Server error: " + b + "(" + status + ")" : b)
				}
			});
		});
		form.getElement('button.nothanks').addEvent('click', function(ev){
			ev.stop();
			toggle.dissolve();
		});
		return function() { 
			reg.inject(startform, 'before');
			toggle.reveal();
		};
	})();
	
	//messaging
	box.scroll = new Fx.Scroll(box, {link:"chain"})
	function addmessage(who, message){
		var ul = box.getElement("ul.conversation")
		if (!ul) {
			ul=new Element("ul", {"class":"conversation"});
			box.grab(ul);
		}
		
		var msg_el = new Element("li", {"class":who.toLowerCase()}).adopt(
			new Element("div", {text:(who.charAt(0).toUpperCase() + who.substr(1).toLowerCase()) + ":", "class":"name"}),
			new Element("div", {text:message, "class":"message"})
		);
		ul.adopt(msg_el);
		box.scroll.toBottom();
		return msg_el;
	}
	function addnotice(msg) {
		return addmessage("system", msg);
	}
	
	//alerts
	var notify = (function() {
		var mimeType = {
			png: 'png',
			gif: 'gif',
			ico: 'vnd.microsoft.icon'
		};
		
		var head = document.getElement('head');
		var title = document.title;
		
		var icons = [ '/img/icons/icon red.png', '/img/icons/icon blue.png' ];
		var infotitle;
		var i=0;
		var messages=0;
		var oldLink = head.getElement('link[rel~=icon]');
		if(oldLink) {
			oldLink.dispose();
		}
		var flasher = false;
		var stopFlashing=function(focused) {
			i=0;
			if(flasher) {
				clearInterval(flasher);
			}
			flasher = false;
			try{ head.getElement('link[rel~=icon]').destroy(); } catch(e){}
			if(oldLink){
				head.adopt(oldLink);
			}
			document.title=title + (focused ? "" : ": " + (infotitle || ""));
		};
		var flash = function() {
			var icon = icons[i%icons.length];
			i=i+1;
			try{
				head.getElement('link[rel~=icon]').destroy();
				var t = (icon && icon.match(/[^\.]+$/)) || ["x-icon"];
				head.adopt(new Element('link').set('href', icon).set('type',"image/" + t[0]).set('rel','icon'));
			} catch(e){}
			document.title = title + (i%2==0 ? ": " + infotitle : "");
			if(i>10) {
				stopFlashing()
			}
		};
		window.addEvents({
			blur: function(){
				messages=0;
				notify=function(){
					messages++;
					infotitle = "" + messages + " New Message" + (messages==1 ? '' : 's');
					if (!flasher){
						i=0;
						flasher = setInterval(flash, 700);
					}
					i=0;
				};
			},
			focus: function(){
				notify=function(){};
				document.title=title;
				stopFlashing(true)
			}
		});
		
		//my oh my ie is dumb. and this is overkill, but whatever.
		if(Browser.Engine.trident){
			$each(document.getElements('body *'), function(el){
				if(el){
					el.addEvents({
						blur: function() {window.fireEvent('blur');},
						focus: function() {window.fireEvent('focus');}
					});
				}
			});
		}
	})();
	
	var alertbox = document.getElement("div.alerts")
	function chatalert(alerttype, msg) {
		var txt = {
			connected: "Connected to a stranger. Have fun.",
			disconnected: "Conversation ended."
		}
		return addmessage("system", msg || txt[alerttype] || alerttype);
		/*
		var al = new Element("div").addClass(alerttype).addClass("hidden").grab(new Element("div", {text: (txt[alerttype] || "unknown alert")}));
		alertbox.grab(al);
		var fx = new Fx.Reveal(al, {mode:"horizontal"}).addEvents({
			show:function(){ setTimeout(function() {fx.dissolve()}, 5000); },
			hide:function(){ al.destroy(); }
		})
		fx.reveal();
		*/
	}
	
	
	var iwastalkingandtheservercrashed;
	function connect() {
		connected = true;
		sendform.getElement("[name=message]").addClass("firsttime").erase("disabled").set('text', 'Type stuff here and press Enter.');
		eraseconversation(box.getElement("ul.conversation"));
		chatalert("connected");
	}
	var listener = function() {
		if (!listenurl) {
			return false;
		}
		listening_request = window.async.request({ url:listenurl, method:'get'}, {
			complete: function(body) {
				if (this.status >= 500) {
					if (!connected) {
						addmessage("error", "The server is down. Try again in a few minutes. (Sorry.)");
						disconnect();
					} else{
						addmessage("error", "Sorry to interrupt, but our server is down. Your conversation will resume as soon as it's up. (Don't leave!)");
						var normal_listener = listener;
						iwastalkingandtheservercrashed = true;
						listener = function() {//pinging thinger
							window.async.request("/api/areyouthere?", {
								complete:function(body){
									listening_request = false;
									if(this.status>=200 && this.status<400) {
										addmessage("notice", "Server is back up. Have fun!");
										listener=normal_listener;
										iwastalkingandtheservercrashed = false;
										setTimeout(listener, 0);
									} else {
										setTimeout(listener, 5000);
									}
								}
							})
						};
					}
				}
				setTimeout(listener, 0); //yee-haw!
				this.fireEvent("defaultComplete", [body]);
			},
			plain: function(resp, status) {
				if (status>=200 && status <400) {
					if(!connected){
						connect();
					}
					notify();
					return addmessage("stranger", resp);
				}
				else {
					addmessage("error", "" + status + " Error: " + resp);
				}
			},
			json: function(j, status) {
				switch(j.type.toLowerCase()) {
					case "notice":
						addmessage("system", j.contents);
						break;
					case "alert":
						if (j.contents=="connected") {
							connect();
						}
						else if (j.contents=="disconnected") {
							if(connected){
								disconnect(chatalert("disconnected", "The stranger ended the conversation."));
							}
						}
						else
							chatalert(j.contents);
						break;
					case "message":
						addmessage("stranger", j.contents);
						break;
				}
			}
		});
	};
	
	
	sendform.addEvent('submit', function(ev) {
		ev && ev.stop();
		var msg = sendform.getElement(".sendbox").value;
		sendform.addClass("sending");
		window.async.request(sendform, {
			success: function(body) {
				addmessage("me", msg);
			},
			error: function(body, status) {
				if ((this.getHeader("content-type") || "").test("^(text|application)/json$")) {
					try{ var j = JSON.decode(body,true); }
					catch(e){ addmessage("error", "Message not sent." + e); return; /*invalid JSON string.*/ }
					var errmsg = {
						flood: {type:'wait',  message:"You're flooding your stranger with messages. "},
						spam:  {type:'error', message:"Hey! Quit spamming! "},
						gone:  {type:'error', message:"Your stranger suddenly disappeared..."}
					};
					$each(j, function(err) {
						var errt = errmsg[err.error];
						addmessage(errt ? errt.type : "error", (errt ? errt.message : "Message not sent. ") + (err.message || ""));
					});
				}
				else{
					var errmsg = {
						404: "page not found",
						502: "the system is down",
						510: "the system is taking its sweet time to send the message",
						500: "the server is freaking out"
					};
					addmessage("servererror", "Message not sent: " + (errmsg[body.trim()] || errmsg[this.status] || "server refused to send it for some reason") + ".");
				}
			},
			complete: function(body) {
				sendform.removeClass("sending").getElement("textarea.sendbox").set("value", "");
				this.fireEvent('defaultComplete');
			}
		});
	});
	
	startform.addEvent('submit', function(ev) {
		ev.stop();
		if (!connected) {
			var ul=box.getElement("ul.conversation");
			if (ul) { eraseconversation(ul); }
			startform.disappear();
			var connecting = addnotice("Authorizing connection...").getElement('.message');
			//connect!!
			window.async.request({ url:this.getProperty('action'), method:this.getProperty('method'), data:this}, {
				plain: function(body, status) {
					if(status>=200 && status <300) {					
						//remove the adescription box
						var info = box.getElement('div.description');
						if(info) {
							new Fx.Reveal(info).addEvent('complete', function(){info.destroy();}).dissolve();
						}
						
						//set the userid wherever needed.
						userid=body;
						[sendform, endform].each(function(f) {
							f.getElement("input[name=id]").set('value', userid);
						});
						var seconds_elapsed = 0;
						function waitey() {
							if(seconds_elapsed>=wait_before_connecting) {
								connecting.set('text', "Connecting...");
								window.async.request({url:"/api/connect", method:"post", data:{id:userid}}, {
									success: function(body) {
										endform.appear();										
										listenurl=this.getHeader('Location') || body.trim();
										connecting.set("text", "Waiting for someone to talk to...");
										setTimeout(listener, 0);
										
									},
									error:function(body, status) {
										disconnect();
										connecting.set("text", "Failed to connect:" + body + " ("+ status + ")");
									}
								});
							}
							else {
								var wait = (wait_before_connecting - seconds_elapsed);
								connecting.set('text', "Connecting in " + wait + (wait==1 ? " second" : " seconds") + "...");
								seconds_elapsed++;
								setTimeout(waitey, 1000);
							}
							
						};
						waitey();
					}
				}, 
				error: function(body, status) {
					addmessage("error", "Server refused to connect with a " + status + " error.");
					startform.appear();
					endform.disappear();
				}
			});
		}
		else {
			addnotice("you're already connected and talking to a stranger...");
		}
	});
	
	function disconnect(disconnect_msg) {
		connected=false; //global-ish chatbox state
		endform.disappear();
		sendform.getElement("[name=message]").set('text', '').set("disabled", "disabled");
		if (listenurl) { //are we listening?
			window.async.request(endform, {
				json: function(j) {
					if (j.action=="begToRegister") {
						register();
					}
				}
			});
			startform.appear();
		}
		listenurl=false;
		if($type(disconnect_msg)=='element'){ //we want to follow-up
			var followup = new Element('form', {method:'post', 'class':'followup', name:'followup', action:'/api/followup'}).adopt(
				new Element('p').set('text', 'Did you like it?'),
				new Element('input', {type:'hidden', name:'id', value:userid}),
				new Element('input', {type:'hidden', name:'liked'}),
				new Element('button', {type:'submit', name:'liked', value:'yes'}).set('html', '<img alt="tick" src="/img/tick.png"/> Yes I did.'),
				new Element('button', {type:'submit', name:'liked', value:'no' }).set('html', '<img alt="cross" src="/img/cross.png"/> Not at all.'),
				new Element('button', {'class':'meh', type:'submit', name:'liked', value:'meh'}).set('html', '<img alt="meh" src="/img/bullet_yellow.png"/> Meh...')
			).addEvent('submit', function(ev) {
				ev.stop();
				async.request(this);
				var liked, message;
				var sentliked = this.getElement('input[name=liked]').get('value');
				if (sentliked=="yes") {
					liked = "likedConversation";
					message = "You liked the conversation.";
				}
				else if (sentliked=="no") {
					liked = "dislikedConversation";
					message = "You didn't like the conversation.";
				}
				else {
					liked = "mehConversation";
					message = "You were totally indifferent about the conversation.";
				}
				addmessage(liked, message);
				this.nix(true);
			});
			followup.inject(disconnect_msg).getElements('button[type=submit]').each(function(el) {
				el.addEvent('click', function(ev) { followup.getElement('input[name=liked]').set('value', this.get('value')); });
				return true;
			});
		}
		
		setTimeout(function(){ //give the server time to respond.
			if(listening_request) {
				listening_request.cancel();
			}
		}, 3000);
		//TODO: submit conversation record.
	};
		
	var disconnectPrompt = (function() {
		var popped=false;
		var popup=document.getElement('div.chatcontainer div.popup');
		var unpop = (function(){
			var t=new Fx.Tween(popup, {duration:'short', property:'opacity'}).addEvent('complete', function(){
				popup.addClass('hidden');
			});
			return function(){ popped=false; t.start(1,0); };
		})();
		
		popup.getElement('div.curtains').addEvent('click', unpop);
		var form=popup.getElement('div.disconnect').getElement('form');
		form.addEvent('submit', function(ev) { ev.stop(); unpop();});
		form.getElement('button.yes').addEvent('click', function() {
			if(popped){
				disconnect(chatalert('disconnected'));
			}
		});
		
		var pop = (function() {
			var t = new Fx.Tween(popup, {duration:'short', property:'opacity'}).addEvent('start', function(){
				popup.setStyle('opacity', 0).removeClass('hidden');
			});
			return function(){
				if (!popped) {
					popped=true;
					t.start(0,1);
				}
			};
		})();
		return pop;
	})();
	
	endform.addEvent('submit', function(ev) {
		ev.stop();
		if (connected) {//in a conversation
			disconnectPrompt();
		}
		else { //just waiting
			var lastMessage = box.getElement("ul.conversation").getLast();
			if (lastMessage.hasClass("system")){
				var lastText = lastMessage.getElement(".message");
				lastText.set('text', lastText.get('text') + " Nevermind.");
			}
			disconnect(); 
		}
	});
	['unload', 'beforeunload'].each(function(name) {
		window.addEvent(name, disconnect);
	});
	
	sendform.getElement("textarea.sendbox").addEvent('keypress', function(ev) {
		if (ev.key == "enter" && !ev.control && !ev.shift) {
			ev.stop()
			if(this.get("value")!="" && ! iwastalkingandtheservercrashed){
				sendform.fireEvent("submit"); //why doesn't sendform.submit() work proper?
			}
		}
	}).addEvent("focus", function(ev){
		if (this.hasClass("firsttime")) {
			this.set("value","").removeClass("firsttime");
		}
	});
};

//fire up the chatbox
window.addEvent("domready", function() {chatbox($('chatbox'), $('sendform'), $('startform'), $('endform')) }); 
var localizeLinks = function(container) {
	container.getElements('a').each(function(el) {
		if (el.hasClass('maily')) {
			var rot13 = function(str){ //+ Jonas Raoni Soares Silva //@ http://jsfromhell.com/string/rot13 [rev. #1]
				return str.replace(/[a-zA-Z]/g, function(c){
					return String.fromCharCode((c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);
				});
			};
			el.addEvent('click', function(ev){
				this.set('href', rot13('znvygb') + ':' + rot13('furyy') + '@' + rot13('fynpg') + '.' + rot13('arg') + rot13('?fhowrpg=Wnlqbr-eryngrq znvy'));
			});
		}
		
		if (
			/^https?:\/\//.test(el.get('href')) //possibly outbound link. crude but sufficient.
			|| /^#/.test(el.get('href')) //anchors
		){ 
			return;
		}
		el.addEvent('click', function(ev) {
			var old = $('chatbox').getElement('div.description');
			var description = old || new Element('div', {'class':'description'}).adopt(new Element('div', {'class':'info'})).set('style', 'display:none;');
			var infodiv = description.getElement('div.info');
			ev.stop();
			description.addClass('loading');
			window.async.request({url:el.get('href'), method: 'get'}, {
				complete: function(body, status) {
					description.removeClass('loading');
					infodiv.set('html', body);
					localizeLinks(infodiv);
					if (!description.getElement('button.okthanks')) {
						new Element('form', {action:''}).inject(infodiv, 'after').adopt(
							new Element('button', {'class':'okthanks', type:'submit'}).set('html', "<img src='/img/tick.png' alt='yep.' />Thanks for the information.")
						).addEvent('submit', function(ev) {
							ev.stop();
							description.nix(true);
						});
					}
					if(!old){
						description.inject($('chatbox'), 'top').reveal();
					} else {
						description.highlight('#EEF9DC');
					}
					try{
						$('chatbox').scroll.toElement(description);
					} catch(e){}
				}
			});
		});
	});
}
window.addEvent('domready', function() { 
	localizeLinks(document.getElement('ul.navigation')); 
	localizeLinks($('chatbox').getElement('.description')); 
});
