// Chat client code
// Some of this code is modified with thanks from code provided by Anant Garg
// Which is Copyright (c) 2009 Anant Garg (anantgarg.com | inscripts.com)
// Used under single domain licence for torn.com

// Other parts of this code are based on code provided by Friendfeed
// Which is licences under the Apache 2.0 licence

// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
//	   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

// Finally, much of this code relies on jQuery, which is GPL (and ace).
// Donation has been made to jQuery.

var windowFocus = true;
var username;
var chatHeartbeatCount = 0;
var minChatHeartbeat = 1000;
var maxChatHeartbeat = 33000;
var chatHeartbeatTime = minChatHeartbeat;
var originalTitle;
var blinkOrder = 0;

var chatboxFocus = new Array();
var newMessages = new Array();
var newMessagesWin = new Array();
var chatBoxes = new Array();

var currentChatBoxes = new Array();
var minChatBoxes = new Array();
var maxChatBoxes = new Array();
var cloChatBoxes = new Array();
var begin = true;

var timeout = 0;
var currentAJAX = {};
var chatRunning = false;
var refreshing_boxes = false;

jQuery = jQuery.noConflict();

function ajaxAbort() {
    console.log ("Aborting AJAX requests and closing rooms");
    jQuery.each(currentAJAX, function(i,type){
        console.log ("Aborting previous thread of type: " + type);
        currentAJAX[i].abort();
    });
    // Close rooms
    jQuery('div').remove('.chatboxbody');
    jQuery('div').remove('.chatboxinput');
    jQuery('div').remove('.chatboxcontent');
    jQuery('div').remove('.chatboxhead');

    chatRunning = false;
}

function setupChannel(callback) {
	// create trampoline that sets it document.domain to be
	// able to talk to the actual channel iframe
	var frameName = 'f' + (Math.random() + "").substring(2, 8);
	jQuery('<iframe src="/js/channel/trampoline.html" name="' + frameName + '" style="display:none"></iframe>')
		.load(function () { window.frames[frameName].setup(callback); })
		.appendTo(document.body);			   
}

jQuery(document).ready(startChat);

function unset_begin(){
	if(begin) begin = false;
}

/* Return a list (array) of the currently open or minimized chat rooms */
function getCurrentlyOpenRooms() {
	return currentChatBoxes;
}

// helper kindly lifted from http://www.alexandre-gomes.com/?p=115
function getScrollBarWidth() {
	var inner = document.createElement('p');
	inner.style.width = "100%";
	inner.style.height = "200px";

	var outer = document.createElement('div');
	outer.style.position = "absolute";
	outer.style.top = "0px";
	outer.style.left = "0px";
	outer.style.visibility = "hidden";
	outer.style.width = "200px";
	outer.style.height = "150px";
	outer.style.overflow = "hidden";
	outer.appendChild (inner);

	document.body.appendChild (outer);
	var w1 = inner.offsetWidth;
	outer.style.overflow = 'scroll';
	var w2 = inner.offsetWidth;
	if (w1 == w2) w2 = outer.clientWidth;

	document.body.removeChild (outer);

	return (w1 - w2);
}

var scrollBarWidth = null;

function restructureChatBoxes() {
	console.log ("Restructuring chat boxes");
	if (scrollBarWidth == null)
		scrollBarWidth = getScrollBarWidth();
	
	// counters for right margins
	var minCount = minChatBoxes.length-1 > 0 ? minChatBoxes.length-1 : 0;
	var maxCount = maxChatBoxes.length-1 > 0 ? maxChatBoxes.length-1 : 0;
	jQuery.each(currentChatBoxes, function(i,chatboxtitle){
		var romin = jQuery.inArray(chatboxtitle, minChatBoxes); // room in minimized boxes list ?
		if(romin == -1) { // not minimized
			jQuery('#chatbox_'+chatboxtitle).css('width','225px');
			jQuery('#chatbox_'+chatboxtitle+' .chatboxcontent').css('display','block');
			jQuery('#chatbox_'+chatboxtitle+' .chatboxinput').css('display','block');
			if(maxCount > 0) { width = maxCount*(225+7); maxCount--; } else { width = 0; }
			jQuery('#chatbox_'+chatboxtitle).css('right', scrollBarWidth + width+'px');
			// scroll boxes to bottom
			jQuery.each(jQuery(".chatboxcontent"), function(){
				jQuery(this).scrollTop(1000);
			});
			if(minChatBoxes.length == 0) {
				jQuery("#chatbox_"+chatboxtitle).css('bottom', '0px');
			} 
			else {
				jQuery("#chatbox_"+chatboxtitle).css('bottom', '38px');
			}
			jQuery('#chatbox_'+chatboxtitle+' .chatboxhead').css('width','209px');
			jQuery('#chatbox_'+chatboxtitle+' .chatboxcontent').css('width','209px');
			//jQuery('#chatbox_'+chatboxtitle+' .chatboxcontent').scrollTop(200 + jQuery('#chatbox_'+chatboxtitle+' .chatboxcontent').scrollHeight);
			if(jQuery.browser.msie) {
				jQuery('#chatbox_'+chatboxtitle+' .chatboxhead').css('width','225px');
				jQuery('#chatbox_'+chatboxtitle+' .chatboxcontent').css('width','225px');
			}
		} else { // minimized
			jQuery('#chatbox_'+chatboxtitle).css('width','116px');
			jQuery('#chatbox_'+chatboxtitle+' .chatboxcontent').css('display','none');
			jQuery('#chatbox_'+chatboxtitle+' .chatboxinput').css('display','none');
			jQuery('#chatbox_'+chatboxtitle+' .chatboxhead').css('width','100px');
			if(minCount > 0) { width = minCount*(116+7); minCount--; } else { width = 0; minCount--; } //first box has zero margin.
			jQuery('#chatbox_'+chatboxtitle).css('right', scrollBarWidth + width + 'px').css('bottom', '0px');
			if(jQuery.browser.msie) {
				jQuery('#chatbox_'+chatboxtitle+' .chatboxhead').css('width','116px');
			}
		}
		if (jQuery("#chatbox_"+chatboxtitle).is(':hidden'))
			jQuery("#chatbox_"+chatboxtitle).show('fast');
	});
	jQuery('.chatbox_menu').css('display', 'none');
	jQuery('.chatboxhead').css('display','block');
	console.log ("Chat boxes are restructured");
}

//&nbsp;<a href="#" onclick="show_mb(\''+chatboxtitle+'\'); return false">__</a>
function createChatBox(chatboxtitle,minimizeChatBox,displayName) {
	jQuery(" <div />" ).attr("id","chatbox_"+chatboxtitle)
	.addClass("chatbox")
	.css('display', 'none') // start off hidden, restructuring will show it
	.html('<div class="chatbox_menu" id="mb_'+chatboxtitle+'" align="left"><a href="#" onclick="closeChatBox(\''+chatboxtitle+'\'); return false">close&nbsp;'+chatboxtitle+'</a></div><div id="bh_'+chatboxtitle+'" class="chatboxhead"><div class="chatboxtitle">'+displayName+'</div><div class="chatboxoptions"></div><br clear="all"/></div><div class="chatboxcontent"></div><div class="chatboxinput"><div class="chatboxnotice"></div><textarea class="chatboxtextarea" onkeydown="return checkChatBoxInputKey(event,this,\''+chatboxtitle+'\')"></textarea></div>')
	.appendTo(jQuery( "body" ));
	
	chatBoxes.push(chatboxtitle);
	var rocur = jQuery.inArray(chatboxtitle, currentChatBoxes);
	if (rocur == -1) { currentChatBoxes.push(chatboxtitle); }
	
	var roclo = jQuery.inArray(chatboxtitle, cloChatBoxes);
	if(roclo != -1) { cloChatBoxes.splice(roclo, 1); }
	
	if (minimizeChatBox == 1) {
		var romin = jQuery.inArray(chatboxtitle, minChatBoxes);
		if(romin == -1) { minChatBoxes.push(chatboxtitle); }
		var romax = jQuery.inArray(chatboxtitle, maxChatBoxes);
		if(romax != -1) { maxChatBoxes.splice(romax,1); }
		jQuery("#chatbox_"+chatboxtitle).css('bottom', '5px');
	} else {
		var romin = jQuery.inArray(chatboxtitle, minChatBoxes);
		if(romin != -1) { minChatBoxes.splice(romin,1); }
		var romax = jQuery.inArray(chatboxtitle, maxChatBoxes);
		if(romax == -1) { maxChatBoxes.push(chatboxtitle); }
		jQuery("#chatbox_"+chatboxtitle).css('bottom', '38px');
	}

	/* This is the blue header */	
	if(!begin) {	
		jQuery("#chatbox_"+chatboxtitle+" .chatboxhead").css('background-color','#0033CC');
	}

	chatboxFocus[chatboxtitle] = false;
	
	jQuery("#chatbox_"+chatboxtitle+" .chatboxtextarea").blur(function(){
		chatboxFocus[chatboxtitle] = false;
		jQuery("#chatbox_"+chatboxtitle+" .chatboxtextarea").removeClass('chatboxtextareaselected');
		jQuery("#chatbox_"+chatboxtitle+" .chatboxhead").css('background-color','#999999');
	}).focus(function(){
		chatboxFocus[chatboxtitle] = true;
		newMessages[chatboxtitle] = false;
		jQuery('#chatbox_'+chatboxtitle+' .chatboxhead').removeClass('chatboxblink');
		jQuery("#chatbox_"+chatboxtitle+" .chatboxtextarea").addClass('chatboxtextareaselected');
		jQuery("#chatbox_"+chatboxtitle+" .chatboxhead").css('background-color','#999999');
	}).keypress(function(){
		jQuery("#chatbox_"+chatboxtitle+" .chatboxhead").css('background-color','#999999');
	});
	
	jQuery("#chatbox_"+chatboxtitle).click(function() {
		if (jQuery("#chatbox_"+chatboxtitle+" .chatboxcontent").css("display") != "none") {
			jQuery("#chatbox_"+chatboxtitle+" .chatboxtextarea").focus();
		}
	});
	// add the double click event to minimized boxes to open them
	jQuery("#chatbox_"+chatboxtitle+" .chatboxhead").click(function() {
		//if(jQuery('#chatbox_'+chatboxtitle+' .chatboxcontent').css('display') == 'none') { // this box is minimized
		toggleChatBoxGrowth(chatboxtitle);
		//}
	});
	
	jQuery(".chatboxtextarea").removeClass('chatboxtextareaselected');
	//jQuery("#chatbox_"+chatboxtitle+" .chatboxtextarea").focus();

	// Counter intutively we dont actually want to do this here as it is done after *all* boxes are open
	// restructureChatBoxes();
}

// function to notify local client boxes // called from updater.showMessage
function notify_box(box){
    if (box != 'Global' && box != 'New_Players' && refreshing_boxes != true) {
        jQuery("#chatbox_"+box+" .chatboxhead").css('background-color', '#0033CC');
    }else{
        console.log ("Not flashing, refresh is " + refreshing_boxes);
    }
}

function show_mb(chatboxtitle) {
	var wid;
	if (jQuery("#chatbox_"+chatboxtitle+" .chatboxcontent").css("display") != "none") { wid = '209px'; } 
	else { wid = '100px'; }
	//alert(wid);
	jQuery('.chatbox_menu').css('display','none');
	jQuery('.chatboxhead').css('display','block');
	jQuery('#bh_'+chatboxtitle).css('display','none');
	jQuery('#mb_'+chatboxtitle).css('width', wid).css('display','block');
	setTimeout("close_mb(\""+chatboxtitle+"\")", 2000);
}

function close_mb(chatboxtitle){
	jQuery('#mb_'+chatboxtitle).css('display','none');
	jQuery('#bh_'+chatboxtitle).css('display','block');
}

function closeChatBox(chatboxtitle) {
        var rocur = jQuery.inArray(chatboxtitle, currentChatBoxes);
        if (rocur != -1) { currentChatBoxes.splice(rocur, 1); }
        var roclo = jQuery.inArray(chatboxtitle, cloChatBoxes);
        if(roclo == -1) { cloChatBoxes.push(chatboxtitle); }

        var romin = jQuery.inArray(chatboxtitle, minChatBoxes);
        if(romin != -1) { minChatBoxes.splice(romin,1); }
        var romax = jQuery.inArray(chatboxtitle, maxChatBoxes);
        if(romax != -1) { maxChatBoxes.splice(romax,1); }

        jQuery('#chatbox_'+chatboxtitle).hide('fast');;
        jQuery('#chatbox_'+chatboxtitle+' .chatboxcontent').css('display','none');
        jQuery('#chatbox_'+chatboxtitle+' .chatboxinput').css('display','none');
        //set_cookie();
        if (currentAJAX['setRooms']) { currentAJAX['setRooms'].abort(); }
        currentAJAX['setRooms'] = jQuery.post("/torncity/chat/setrooms/",
                   { "room": chatboxtitle, "status": 2, "_xsrf": getCookie("_xsrf") }, // 2 for closed
                        function(data){}, "json");
        restructureChatBoxes();
}

function toggleChatBoxGrowth(chatboxtitle) {
	var rocur = jQuery.inArray(chatboxtitle, currentChatBoxes);
	if (rocur == -1) { currentChatBoxes.push(chatboxtitle); }
	var roclo = jQuery.inArray(chatboxtitle, cloChatBoxes);
	if(roclo != -1) { cloChatBoxes.splice(roclo,1); }
	var romin = jQuery.inArray(chatboxtitle, minChatBoxes);
	var romax = jQuery.inArray(chatboxtitle, maxChatBoxes);
	if (jQuery('#chatbox_'+chatboxtitle+' .chatboxcontent').css('display') == 'none') {	 
		if(romin != -1) { minChatBoxes.splice(romin,1); }
		if(romax == -1) { maxChatBoxes.push(chatboxtitle); }
		jQuery("#chatbox_"+chatboxtitle+" .chatboxhead").css("background-color","#999999");
		jQuery(".chatboxtextarea").removeClass("chatboxtextareaselected");
		jQuery("#chatbox_"+chatboxtitle+" .chatboxtextarea").focus();
		// scroll to bottom
		jQuery("#chatbox_"+chatboxtitle+" .chatboxcontent").scrollTop(1000);
		if (currentAJAX['setRooms']) { currentAJAX['setRooms'].abort(); }
		currentAJAX['setRooms'] = jQuery.post("/torncity/chat/setrooms/", 
		   { "room": chatboxtitle, "status": 0, "_xsrf": getCookie("_xsrf") }, // 0 for maximized
			function(data){}, "json");
		
	} else {
		if(romax != -1) { maxChatBoxes.splice(romax,1); }
		if(romin == -1) { minChatBoxes.push(chatboxtitle); }
		if (currentAJAX['setRooms']) { currentAJAX['setRooms'].abort(); }
		currentAJAX['setRooms'] = jQuery.post("/torncity/chat/setrooms/", 
		   { "room": chatboxtitle, "status": 1, "_xsrf": getCookie("_xsrf")  }, // 1 for minimized
			function(data){}, "json");
	} 
	restructureChatBoxes();
}

/* This is called when we press enter with a new message in a chat box */
function checkChatBoxInputKey(event,chatboxtextarea,chatboxtitle) {
	if(event.keyCode == 13 && event.shiftKey == 0)	{
		message = jQuery(chatboxtextarea).val();
		message = message.replace(/^\s+|\s+$/g,"");

		jQuery(chatboxtextarea).val('');
		jQuery(chatboxtextarea).focus();
		jQuery(chatboxtextarea).css('height','44px');

		if (message != '') {
			console.log ("New message" + message);
			newMessage(message, chatboxtitle);
		}
		chatHeartbeatTime = minChatHeartbeat;
		chatHeartbeatCount = 1;
		return false;

		var adjustedHeight = chatboxtextarea.clientHeight;
		var maxHeight = 94;

		if (maxHeight > adjustedHeight) {
			adjustedHeight = Math.max(chatboxtextarea.scrollHeight, adjustedHeight);
			if (maxHeight)
				adjustedHeight = Math.min(maxHeight, adjustedHeight);
			if (adjustedHeight > chatboxtextarea.clientHeight)
				jQuery(chatboxtextarea).css('height',adjustedHeight+8 +'px');
		} else {
			jQuery(chatboxtextarea).css('overflow','auto');
		}
	}
}

function onGetRooms(data) {
    console.log ("Retrieved the following data for rooms: " +data);
    data = eval("(" + data + ")"); 
    jQuery.each(data.rooms, function(i,room){
        console.log ("Looking at room "+room[0]);
        switch (+room[1]) {
            case 0:
                currentChatBoxes.push(room[0]);
                maxChatBoxes.push(room[0]);
                createChatBox(room[0], 0, room[2]); return true;
            case 1:
                currentChatBoxes.push(room[0]);
                minChatBoxes.push(room[0]);
                createChatBox(room[0], 1, room[2]); return true;
        }
    });
    console.log ("All rooms opened, restructuring and starting poll");
    updater.poll();
    restructureChatBoxes();
    jQuery("body").focus();
    chatRunning = true;
}

function onGetRoomsError(err) {
    chatRunning = false;
    console.log ("Error getting rooms -  "+err.message);
}

function addHtmlToChatBox(room, html) {
	var c = jQuery("#chatbox_"+room+" .chatboxcontent");
	c.append(html);
	c.scrollTop(c.get(0).scrollHeight + 50);
}

function newMessage(thismessage, thisroom) {
    jQuery("#chatbox_"+thisroom+" .chatboxtextarea").attr('disabled','disabled');
    thismessage = thismessage.replace(/&/g,'');
    if (thismessage == '')
        thismessage = ' ';

    var data = "body=" + thismessage + "&room=" + thisroom;
	
    if (currentAJAX.newMessage)
        currentAJAX.newMessage.abort();

    currentAJAX.newMessage = updater.channeledAjax({
        type: "POST",
        url: "/torncity/chat/message/new",
        data: data,
        timeout: 20000,
        success: function(msg){
            jQuery("#chatbox_"+thisroom+" .chatboxtextarea").attr('disabled','').focus();
            console.log ("Submitted OK");
            begin = false; 
        },
        error: function(xhr, status, error) {
            console.log ("Error trying to submit");
            xhr.abort();
            addHtmlToChatBox(thisroom, '<div class="error">Sorry, failed to send message...</div>');
            // add back the text so it doesn't disappear completely
            jQuery("#chatbox_"+thisroom+" .chatboxtextarea")
                .val(thismessage).attr('disabled','').focus();
            }
        });
}

function setChatBoxNotice(notice) {
	jQuery(".chatboxnotice").text(notice);
}

var updater = {
	roomsLength: 0,
	cursors: {},
	failHappened: null,
	channel: null, // ajax function in iframe
	timeout: null,
	
	poll: function() {
		console.log ("Poll called");
		var rooms = getCurrentlyOpenRooms();
		updater.roomsLength = rooms.length;
		for ( var i=updater.roomsLength-1; i>=0; --i ){
			room = rooms[i];
			// If room does not have cursor set, create room element with NULL cursor
			if (!updater.cursors[room])
				updater.cursors[room] = "";
		}
		
		setTimeout(updater.updateReq, 200);
		setTimeout(unset_begin, 1000);
	},

	onSuccess: function(response) {
		setChatBoxNotice("");
		jQuery(".chatboxtextarea").attr('disabled', '');
		updater.failHappened = null;
		console.log ("update request returns sucess");
		try {
			updater.newMessages(eval("(" + response + ")"));
		} catch (e) {
			updater.onError(response);
		}
		//currentAJAX.abort();
                refreshing_boxes = false;
		console.log ("Starting new update request");
		updater.scheduleUpdateReq(200);

	},
	
	onError: function (XMLHttpRequest, status, errorThrown) {
		// possible reasons for error: timeout, lost connection, navigating away

		if (status == "timeout") {
			// timeout generally means we're good, there just wasn't
			// anything to report in the other end, so just reschedule
			console.log("Timeout, reconnecting");
			updater.failHappened = null;
			setChatBoxNotice("");
			jQuery(".chatboxtextarea").attr('disabled', '');
			updater.scheduleUpdateReq(200);
			return;
		}
		
		if (updater.failHappened == null)
			updater.failHappened = new Date();

		var secondsSince = ((new Date()).getTime() - updater.failHappened.getTime()) / 1000;
		
		var nextTry;
		if (secondsSince < 2)
			nextTry = 1;
		else if (secondsSince < 5)
			nextTry = 2;
		else if (secondsSince < 10)
			nextTry = 5;
		else if (secondsSince < 30)
			nextTry = 10;
		else if (secondsSince < 60)
			nextTry = 20;
		else if (secondsSince < 120)
			nextTry = 60;
		else
			nextTry = 120;
               nextTry = nextTry * 2;
		//addHtmlToChatBox("Staff", "<div>Next try in " + nextTry + " seconds</div>");
		console.log("Error" + errorThrown + ", next try in " + nextTry + " seconds");

		if (secondsSince > 30) {
			// offline for too long
			setChatBoxNotice("You're offline");
			jQuery(".chatboxtextarea").attr('disabled', 'disabled');
		}
		else {
			setChatBoxNotice("");
			jQuery(".chatboxtextarea").attr('disabled', '');
		}

		updater.scheduleUpdateReq(nextTry * 1000);
	},

	scheduleUpdateReq: function(msecs) {
		// make sure we're the only one running
		clearTimeout(updater.timeout);
		
		updater.timeout = setTimeout(updater.updateReq, msecs);
	},
	
	newMessages: function(response) {
		//console.log ("Error + no of messages: "+ response.messages.length);
		if (response.messages.length == 0) return;
		var msgs = response.messages;
		var room_msgs = new Array();
		for (var i = 0; i < msgs.length; i++) {
			var room = msgs[i].room;
			updater.cursors[room] = msgs[i].id; // this is done per item
                        
			if (jQuery.inArray(room_msgs, room) == -1) { room_msgs[room] = 1; }
			else { room_msgs[room] += 1; }
			for (var j = 0; j < room_msgs[room]; j++) {
				if(j != (room_msgs[room]-1)) { // last message in each room
					updater.showMessage(msgs[i], msgs[i].room, msgs[i].from, response.to_user, null);
				} else {
					updater.showMessage(msgs[i], msgs[i].room, msgs[i].from, response.to_user, msgs[i].date);			
				}
			}
		}
	},

	showMessage: function(message, room, frm, tou, dat) {
		var existing = jQuery("#m" + message.id);
		if (existing.length > 0) { return; }
		var node = jQuery(message.html);
		if((frm != tou) && (!begin)) { 
                        console.log ("Message in room "+room+" is new, we have done populating our boxes");
			notify_box(room);
		}
                jQuery("#chatbox_"+room+" .chatboxcontent").append(node);

                /* Flashing effect for all othe than city */
                node.slideDown("fast", function() {
                    jQuery("#chatbox_"+room+" .chatboxcontent").scrollTop(jQuery("#chatbox_"+room+" .chatboxcontent")[0].scrollHeight + 50);
                });

		// add timestamp of the last message box, keep in last line
		if (dat != null) {
			node.attr('title',dat);
			jQuery('.timestamp_'+room).css('display','none');
			jQuery("#chatbox_"+room+" .chatboxcontent").append("<div class=\"timestamp_"+room+"\" style=\"color:#666666; display:block; margin:0\"><i>Last message:</i> "+dat+" - TCT</div>");
		}
	},

	updateReq: function() {
		if (updater.roomsLength == 0)
			return;
		
		console.log ("Sending AJAX update request");
		
		var json = {};
		json['_xsrf'] = getCookie("_xsrf");


                rooms = getCurrentlyOpenRooms();
                size = jQuery(".message").size();
		max_size = rooms.length*200;
                console.log ("Total message size: "+size);
                if (size >= max_size) {
                    console.log ("Purging old messages");
                    updater.cursors = {};
                    roomslength = rooms.length;
                    for ( var i=roomslength-1; i>=0; --i ){
                        room = rooms[i];
                        console.log ("Processing room "+room);
                        updater.cursors[room] = "";
                    }
                    jQuery('div').remove('.message');
                    console.log ("*AFTER CLEANUP* Total message size: "+size);
                    refreshing_boxes = true; // Dont flash on return
                }
                size = jQuery(".message").size();


		json['cursors'] = jQuery.toJSON(updater.cursors);
		if (currentAJAX.updateMessages)
			currentAJAX.updateMessages.abort();

		currentAJAX.updateMessages = updater.channeledAjax({
			url: "/torncity/chat/message/updates",
			type: "POST",
			dataType: "text",
			data: json,
			success: updater.onSuccess,
			error: updater.onError,
			// set a timeout so we can detect whether the other end
			// is still alive
			timeout: 600000000
		});
	},
	
	channeledAjax: function(o) {
		var cookies = {};
		cookies['PHPSESSID'] = jQuery.cookie('PHPSESSID');
		cookies['secret'] = jQuery.cookie('secret');

		var abort = updater.channel(o, cookies);
		
		// pack abort in nicely, we can't return the real xhr object
		// since it's in the (inaccessible) iframe
		return { abort: abort };
	}
};


function startChat() {
    if (chatRunning == true) {
        console.log ("Chat already running");
        return;
    }else{
        console.log ("Starting chat in frame");
    }

    /*originalTitle = document.title;*/
    console.log ("Starting chat in parent window");
    /* It is critical to kill the AJAX requests running in IE as soon as user tries to navigate
    Otherwise they can not go anywhere, and browser appears crashed */
    window.onbeforeunload = function(){
        console.log ("Aborting AJAX calls");
        ajaxAbort();
    };	
    try {
        startChatSession();
    } catch (err){
        console.log ("Unable to restructure chat boxes - probably user not yet logged in. Error " + err);
	ajaxAbort();
        chatRunning = false;
    }
}

function startChatSession() { 
	console.log ("Starting chat sessions");
	if (currentAJAX['getRooms']) { currentAJAX['getRooms'].abort(); }
	setupChannel(function (channel) {
		updater.channel = channel;
	});
	url = "/torncity/chat/getrooms/?_xsrf=&rand=" + myTimestamp();
        currentAJAX.updateMessages = updater.channeledAjax({
                        url: url,
                        type: "GET",
                        dataType: "text",
                        //data: json,
                        success: onGetRooms,
                        error: onGetRoomsError,
                        // set a timeout so we can detect whether the other end
                        // is still alive
                        timeout: 10000
        });
}


// new json encode plugin
// http://code.google.com/p/jquery-json/

(function(jQuery){jQuery.toJSON=function(o)
{if(typeof(JSON)=='object'&&JSON.stringify)
return JSON.stringify(o);var type=typeof(o);if(o===null)
return"null";if(type=="undefined")
return undefined;if(type=="number"||type=="boolean")
return o+"";if(type=="string")
return jQuery.quoteString(o);if(type=='object')
{if(typeof o.toJSON=="function")
return jQuery.toJSON(o.toJSON());if(o.constructor===Date)
{var month=o.getUTCMonth()+1;if(month<10)month='0'+month;var day=o.getUTCDate();if(day<10)day='0'+day;var year=o.getUTCFullYear();var hours=o.getUTCHours();if(hours<10)hours='0'+hours;var minutes=o.getUTCMinutes();if(minutes<10)minutes='0'+minutes;var seconds=o.getUTCSeconds();if(seconds<10)seconds='0'+seconds;var milli=o.getUTCMilliseconds();if(milli<100)milli='0'+milli;if(milli<10)milli='0'+milli;return'"'+year+'-'+month+'-'+day+'T'+
hours+':'+minutes+':'+seconds+'.'+milli+'Z"';}
if(o.constructor===Array)
{var ret=[];for(var i=0;i<o.length;i++)
ret.push(jQuery.toJSON(o[i])||"null");return"["+ret.join(",")+"]";}
var pairs=[];for(var k in o){var name;var type=typeof k;if(type=="number")
name='"'+k+'"';else if(type=="string")
name=jQuery.quoteString(k);else
continue;if(typeof o[k]=="function")
continue;var val=jQuery.toJSON(o[k]);pairs.push(name+":"+val);}
return"{"+pairs.join(", ")+"}";}};jQuery.evalJSON=function(src)
{if(typeof(JSON)=='object'&&JSON.parse)
return JSON.parse(src);return eval("("+src+")");};jQuery.secureEvalJSON=function(src)
{if(typeof(JSON)=='object'&&JSON.parse)
return JSON.parse(src);var filtered=src;filtered=filtered.replace(/\\["\\\/bfnrtu]/g,'@');filtered=filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']');filtered=filtered.replace(/(?:^|:|,)(?:\s*\[)+/g,'');if(/^[\],:{}\s]*$/.test(filtered))
return eval("("+src+")");else
throw new SyntaxError("Error parsing JSON, source is not valid.");};jQuery.quoteString=function(string)
{if(string.match(_escapeable))
{return'"'+string.replace(_escapeable,function(a)
{var c=_meta[a];if(typeof c==='string')return c;c=a.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+(c%16).toString(16);})+'"';}
return'"'+string+'"';};var _escapeable=/["\\\x00-\x1f\x7f-\x9f]/g;var _meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};})(jQuery);

// jQuery cookie plugin http://plugins.jquery.com/files/jquery.cookie.js.txt
jQuery.cookie=function(B,I,L){if(typeof I!="undefined"){L=L||{};if(I===null){I="";L.expires=-1}var E="";if(L.expires&&(typeof L.expires=="number"||L.expires.toUTCString)){var F;if(typeof L.expires=="number"){F=new Date();F.setTime(F.getTime()+(L.expires*24*60*60*1000))}else{F=L.expires}E="; expires="+F.toUTCString()}var K=L.path?"; path="+(L.path):"";var G=L.domain?"; domain="+(L.domain):"";var A=L.secure?"; secure":"";document.cookie=[B,"=",encodeURIComponent(I),E,K,G,A].join("")}else{var D=null;if(document.cookie&&document.cookie!=""){var J=document.cookie.split(";");for(var H=0;H<J.length;H++){var C=jQuery.trim(J[H]);if(C.substring(0,B.length+1)==(B+"=")){D=decodeURIComponent(C.substring(B.length+1));break}}}return D}};
