
/******************************************/
/***  bozz v2.0 by zayda (c) 2000-2002  ***/
/******************************************/

var loadScript = "http://" + window.location.host + "/core/core.php";
var loginUrl = "/bozz2/login.php?url=/client/default/";
var refTime = defRefTime = 8;
var codes = new Array();
codes[0] 			= "bez chyby";
codes.invalidId		= "Identifikátor pripojení (ji) není platný.\n(patrně tě vyhodil automaticky bozz kvůli nečinnosti\na nebo moná některý ze správců; více informací v nápovědě)";
codes.relogged		= "Přehlásil(a) ses znovu z jiného klienta.";
codes.logouted		= "Úspěně ses odhlásil(a) z bozzu.";
codes.roomLocked	= "Místnost je uzamčena!";
codes.outOfSynchro	= "Vyprel timeout spojení se serverem bozzu.\nBuď server nebeí, nebo jsi s ním ztratil(a) spojení,\nnebo je spojení príli pomalé.\nZkus se znovu pripojit.";

var evMsg = 0;
var evUser = 1;
var evDelUser = 2;
var evActUser = 3;
var evRoom = 4;
var evDelRoom = 5;
var evCountRoom = 6;
var evSound = 7;
var evReset = 8;
var evLogout = 9;

var events = new Array();
events[evMsg] = new Array("Msg", "time", "from", "to", "text");
events[evUser] = new Array("User", "name", "sex", "level", "idle", "status", "icon", "crystals", "pos_x", "pos_y");
events[evDelUser] = new Array("User", "name");
events[evActUser] = new Array("User", "name", "status");
events[evRoom] = new Array("Room", "name", "owner", "locked", "hidden", "password", "type", "icon", "count", "reserved_1", "reserved_2");
events[evDelRoom] = new Array("Room", "name");
events[evCountRoom] = new Array("Room", "name", "count");
events[evSound] = new Array("Sound", "url");
events[evReset] = new Array("Reset", "user", "room");
events[evLogout] = new Array("Logout");

var evNames = new Array("Msg", "User", "DelUser", "ActUser", "Room", "DelRoom", "CountRoom", "Sound", "Reset", "Logout");
var intFields = new Array("level", "idle", "locked", "hidden", "password", "type", "count");

function user_sort(user1, user2) { return user1.idle-user2.idle; }

/************************/
/***	třída Chat	  ***/
/************************/
Chat = function()
{
	this.reset = function()
	{
		this.myName = "";
		this.myRoom = "";
		this.ID = "";
		this.eid = "";	
		this.Msgs = new Array();
		this.lastMsgs = new Array();
		this.Users = new Array();
		this.Rooms = new Array();
		this.running = false;
		this.code = 0;
		this.refCounter = 0;		
		this.lastUpdate = new Date();
		this.resetHandlers();
	}

	this.debugInfo = function()
	{
		var str = "bozz debug info\n---------------\n";
		for (var key in this) if (typeof this[key] != "function") str += key+"="+this[key]+"\n";
		alert(str);
	}
	
	this.resetHandlers = function()
	{
		this.onMsg = function() {}
		this.onUser = function() {}
		this.onDelUser = function() {}
		this.onActUser = function() {}
		this.onRoom = function() {}
		this.onDelRoom = function() {}
		this.onSound = function(url) {}
		this.onLoadStart = function() {}
		this.onLoadEnd = function() {}
		this.onReset = function() {}
		this.onLogout = function() {}
	}
	
	this.inspect = false;
	this.debug = false;
	this.loading = false;
	this.timeoutId;
	this.reset();

	/*** veřejné metody třídy Chat ***/

	// Chat.init zahájí synchronizaci s přihláením s identifikátorem ID
	this.init = function(ID) 
	{
		this.ID = ID; 
		this.code = 0;
		this.running = true;
		this.refCounter = 0;		
		if (typeof this.timeoutId != "undefined") window.clearTimeout(this.timeoutId);
		this.refresh();
	}
	
	// Chat.say odesílá zprávu (příkaz, začíná-li zpráva znakem lomítka)
	this.say = function(msg) 
	{
		var up_msg = msg.toUpperCase();
		if (up_msg == "/DEBS")
		{
			this.debug = !this.debug;
			alert("bozz: debug server = "+this.debug);
		}
		else if (up_msg == "/DEBC")
		{
			this.inspect = !this.inspect;
			alert("bozz: debug client = "+this.inspect);
		}
		else if (up_msg == "/SLOWREF")
		{
			refTime = refTime == defRefTime ? 60 : defRefTime; 
			alert("bozz: pomalý refresh je "+(refTime == defRefTime ? "vypnut" : "zapnut")+".");
		}
		else if (up_msg == "/H" || up_msg == "/HELP") window.open("/bozz2/help.php"); else
		if (up_msg == "/C" || up_msg == "/CLEAR" || up_msg.substring(0, 3) == "/C " || up_msg.substring(0, 7) == "/CLEAR ")
		{
			var arr = up_msg.split(" ");
			this.cutMsgs(arr[1] ? arr[1] : 0);
			this.onMsg();
		}
		else this.load("msg="+urlEncode(msg));
	}

	// Chat.moveTo je ekvivalentní volání Chat.say("/j room"), navíc pokud je místnost uzamčena resp. zaheslována, provede Alert resp. Confirm; typicky se tato funkce pouívá v klikacím seznamu místností 
	this.moveTo = function(room)		
	{
		var myLevel = this.Users[this.myName].level;
		if (room == this.myRoom) {} else
		if (typeof this.Rooms[room] != "object") this.say("/j "+room); else
		if (this.Rooms[room].locked&&(myLevel < 3)&&(this.Rooms[room].owner != this.myName)) alert("bozz:\nMístnost "+room+" je zamčena."); else
		{
			if (this.Rooms[room].password&&myLevel<3&&(this.Rooms[room].owner != this.myName)) var password = prompt("bozz:\nMístnost "+room+" je zaheslována. Zadej prosím její přístupové heslo:\n\n", ""); else var password = " ";
			if ((password != null)&&(password != "")) this.say("/j "+room+" "+password);
		}
	}

	// Chat.redraw vyvolá ovladače překreslující obsah klienta
	this.redraw = function()
	{
		this.onReset();
		this.onUser();
		this.onRoom();
		this.onMsg();
	}
	
	// Chat.exit	
	this.exit = function() { this.say("/e"); }				

	// Chat.setCode zobrazí Alert() s popisem chybového kódu a nastaví pole Chat.code (tím se zastaví periodické volání Chat.refresh())
	this.setCode = function(code) { alert("bozz:\n"+codes[code]); this.code = code; }

	// Chat.completeName doplní jméno uivatele (místnosti) na konci zadané zprávy; typicky se pouívá při události onChange v inputboxu, ve kterém se píí zprávy do chatu
	this.completeName = function(msg)
	{
		var names = new Array(), i = 0,	count = 0;
		for (var name in this.Users) names[i++] = name;
		for (var name in this.Rooms) names[i++] = name;
		inputStr = msg.toLowerCase();
		startPos = inputStr.lastIndexOf(" ");
		startPos++;
		inputStr = inputStr.substring(startPos, inputStr.length);
		strLen = inputStr.length; 
		for (i=0; i<names.length; i++) if ((names[i].substring(0,strLen).toLowerCase() == inputStr)&&(strLen > 0)) { count++; ni = i; }
		if (count == 1)	
		{
			msg = msg.substring(0, startPos) + names[ni];
			if (!startPos) msg += ": "; else msg += " ";
		}
		return msg;
	}

	// Chat.playSound přehraje zvuk uloený v souboru na zadané url adrese
	this.playSound = function(url) {}

	/*** soukromé metody třídy Chat ***/ 

	// Chat.load načte load skript se zadanými parametry (ve formátu "par=value&par2=value2")
	this.load = function(params)
	{
		if (this.running)
		{
			this.onLoadStart();
			var date = new Date(); url = loadScript+"?ID="+this.ID+"&time="+date.getTime();
			if (this.eid) url += "&eid="+this.eid;
			if (this.debug) url += "&debug=1";
			if (params) url += "&"+params;
			this.loading = true;
			window.frames.load.location.href = url;
		}
	}
	
	// Chat.refresh periodicky načítá load skript a tak zajiuje synchronizaci dat se serverem; navíc inkrementuje vlastnost idle vech uivatelů v poli Chat.Users[]
	this.refresh = function()
	{
		var now = new Date(); 
		if (now.getSeconds() - this.lastUpdate.getSeconds() > 60)
		{
			this.setCode("outOfSynchro");
			window.top.location.href = "/";
		}
		else 
		{
			for (var name in this.Users) this.Users[name].idle += refTime;
			if (this.refCounter%6==1) this.onUser();
			if (!this.loading && !this.code) { this.load(); this.refCounter++; }
			if (!this.code) this.timeoutId = setTimeout("b.refresh()", refTime * 1000);
		}
	}

	// Chat.up(date) volá load skript, pokud přibyly nové události - funkce je pak načte do datových polí objektu Chat
	this.up = function(eid, evStr)
	{
		this.lastMsgs = new Array();
		if (typeof evStr == "string") var data = evStr.split("\t"); else var data = new Array();
		var pos = 0, handlers = new Array();
		this.eid = eid; 
		if (this.running) while (pos < data.length-1)
		{
			var evCode = data[pos++];
			if (this.inspect)
			{
				var output = "evCode "+evCode+" ("+evNames[evCode]+"):\n----------------\n";
				if (typeof events[evCode] != "object") output += "unknown (!)\n"; else
					for (var i=1; i<events[evCode].length; i++) output += events[evCode][i]+"="+data[pos+i-1]+"\n";
				output += "\nevStr:\n----------------\n"+evStr;
				alert(output);
			}
			if ((evCode == evMsg)||(evCode == evUser)||(evCode == evRoom))
			{
				var key = (evCode == evMsg)?this.Msgs.length:data[pos], arrName = events[evCode][0]+"s";
				this[arrName][key] = new Array();
				for (var i=1; i<events[evCode].length; i++)			 
				{
					for (var j=0; j<intFields.length; j++) if (events[evCode][i] == intFields[j]) { data[pos] = data[pos]-0; break; }
					this[arrName][key][events[evCode][i]] = (events[evCode][i] == "text")?formatMsg(data[pos++]):data[pos++];
				}
				if (evCode == evMsg) this.lastMsgs[this.lastMsgs.length] = this.Msgs[this.Msgs.length-1];
				handlers[events[evCode][0]] = true;
			}
			else if ((evCode == evDelUser)||(evCode == evDelRoom))
			{
				delete this[events[evCode][0]+"s"][data[pos]];
				if (evCode == evDelUser) this.onDelUser(data[pos++]); else this.onDelRoom(data[pos++]);
			}
			else if (evCode == evCountRoom)
			{
				var name = data[pos++];
				this.Rooms[name].count += (data[pos++]-0);
				handlers.Room = true;
			}
			else if (evCode == evActUser) 
			{ 
				if (typeof this.Users[data[pos]] == "object")
				{
					var name = data[pos++];
					this.Users[name].status = data[pos++];
					if (this.Users[name].status != "A") this.Users[name].idle = 0;
				}
				handlers.User = true; 
			}
			else if (evCode == evSound) this.onSound(data[pos++]);
			else if (evCode == evReset)
			{
				this.myName = data[pos++];
				this.myRoom = data[pos++];
				this.Msgs = new Array();
				this.Users = new Array();
				this.onReset();
				this.onMsg();
			}
			else if (evCode == evLogout)
			{
				if (data[pos] == 0) var code = "logouted";
				if (data[pos] == 1) var code = "invalidId";
				if (data[pos] == 2) var code = "relogged";
				pos+=999999;
				this.setCode(code);
				this.onLogout();
				this.reset();
				window.frames.client.location.href = loginUrl;
			}
		}
		// cut msg array
		if (this.Msgs.length > 320) this.cutMsgs(300);
		// sort users
		var dummy = new Array(), i = 0;
		for (var name in this.Users) dummy[i++] = this.Users[name];
		dummy.sort(user_sort);
		this.Users = new Array();
		for (i=0; i<dummy.length; i++) this.Users[dummy[i].name] = dummy[i];
		
		this.loading = false;
		this.onLoadEnd();
		for (var key in handlers) eval("if (typeof(b.on"+key+")=='function') b.on"+key+"();");
	}
	
	this.cutMsgs = function(num)
	{
		if (num < this.Msgs.length)
		{
			var dummy = new Array(), j = 0;
			for (var i=this.Msgs.length-num; i<this.Msgs.length; i++) dummy[j++] = this.Msgs[i];
			this.Msgs = dummy;
		}
	}
}

//*** různé dalí uitečné funkce (pouívané metodami třídy Chat) ***/
function urlEncode(str) 
{ 
 	var hex_tab = "0123456789ABCDEF", result = "", ascii_tab = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ Ą˘Ł¤ĽŚ§¨ŠŞŤŹ­ŽŻ°ą˛ł´ľśˇ¸šşťź˝žżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙";
	for (var i=0; i<str.length; i++)
	{
		var chr = str.charAt(i), ord = ascii_tab.indexOf(chr)+32;
		if (ord==32) result += "+"; 
		else if  (((ord>47)&&(ord<58))||((ord>64)&&(ord<91))||((ord>95)&&(ord<122))||(chr==".")||(chr=="/")) result += chr; else result += "%"+hex_tab.charAt(Math.floor(ord/16))+hex_tab.charAt(ord%16);	
	}
	return result; 
}

function ascii7(str)
{
	var str2 = "", tab1 = "ěčřýáíéóůúÉĚČŘÝÁÍÉÓŮÚďĎňŇ", tab2 = "escrzyaieouuEESCRZYAIEOUUdDtTnN";
	for (var i=0; i<str.length; i++) 
	{
		chr = str.charAt(i);
		for (var j=0; j<tab1.length; j++) if (chr == tab1.charAt(j)) chr = tab2.charAt(j);
		str2 += chr;
	}
	return str2;
}

function parseDate(date, shortd)
{
	var minutes = date.getMinutes();
	if (minutes<10) minutes = "0"+minutes;
	var month = date.getMonth()+1;
	if (month<10) month = "0"+month;
	var day = date.getDate();
	if (day<10) day = "0"+day;
	var hours = date.getHours();
	if (hours<10) hours = "0"+hours;
	str = hours+":"+minutes;
	if (!shortd) str = day+"."+month+"."+date.getYear()+" "+str;
	return str;
}

function str_replace(needle, needle2, haystack)
{
	var arr = haystack.split(needle);
	var str = arr[0];
	for (i=1; i<arr.length; i++) str += needle2+arr[i];
	return str;  
}

function formatMsg(msg)
{
	msg = str_replace("\n", "<br>", str_replace("<", "&lt;", str_replace(">", "&gt;", str_replace("&", "&amp", msg))));
	var arr = msg.split("http://");
	msg = arr[0];
	for (var i=1; i<arr.length; i++)
	{
		var pos = arr[i].indexOf(" "); 
		var url = arr[i].substring(0, pos>-1?pos:99999);
		var ext = url.substring(url.lastIndexOf(".")+1);
		ext = ext.toLowerCase();
		if (ext == "jpg"||ext == "jpeg"||ext == "gif") msg += "<img src=\"http://"+url+"\">"; else msg += "<a href=\"http://"+url+"\" target=_blank>"+url+"</a>";
		if (pos>-1) msg += arr[i].substring(pos);
	}
	arr = msg.split("%");
	msg = arr[0]; 
	for (i=1; i<arr.length; i++) if (!arr[i].length) msg += "%"; else switch (arr[i].charAt(0).toUpperCase())
	{
		case "0":
		case "1":
		case "2":
		case "3":
			msg += "<span class=\"size"+arr[i].charAt(0)+"\">"+arr[i].substring(1)+"</span>";
			break;
		case "B":
		case "U":
			msg += "<"+arr[i].charAt(0)+">"+arr[i].substring(1)+"</"+arr[i].charAt(0)+">";
			break;
		case "_":
			msg += "&nbsp;"+arr[i].substring(1);
			break;
		default:
			if (i==1) msg += "%";
			msg += arr[i];
	}
	return msg;
}

