function sb_navigate_helper(urlX){
	document.location.href = urlX;
	return false;
}

Object.extend = function(destination, source) {
  for (property in source) {
    destination[property] = source[property];
  }
  return destination;
};

String.prototype.sReplace = function(find, replace) {
	return this.split(find).join(replace);
};

var YShout = function() { this.init.apply(this, arguments); }

var yShout;

YShout.prototype = {
	init: function(options) {
		yShout = this;
		if ($('#yshout').size() == 0) return;

		var dOptions = {
			yPath: './addons/yshout/',
			log: 1
		};

		this.options = Object.extend(dOptions, options);
		//alert(this.options.isLongVersion);
		this.ajax(this.initialLoad, {
			reqType: 'init',
			yPath: this.options.yPath,
			log: this.options.log
		});

		this.postNum = 0;

	},

	initialLoad: function(updates) {
		this.d('In initialLoad');
		this.prefs = updates.prefs;
		this.initForm();
		this.initRefresh();
		this.initCP();
		if (this.prefs.flood) this.initFlood();

		if (updates.nickname)
			$('#ys-input-nickname')
				.removeClass( 'ys-before-focus')
				.addClass( 'ys-after-focus')
				.val(updates.nickname);

		if (updates)
			this.updates(updates);
	},

	initForm: function() {
		this.d('In initForm');
		var yPath = this.options.yPath ? this.options.yPath : './addons/yshout/';
		var log = this.options.log ? this.options.log : 1;
		var timeOffset = this.options.timeOffset ? this.options.timeOffset : '0';
		var inputUsername = this.options.inputUsername ? this.options.inputUsername : false;
		var inputUID = this.options.inputUID ? this.options.inputUID : '1';
		var inputColor = this.options.inputColor ? this.options.inputColor : '';
		var constLanguage = this.options.constLanguage ? this.options.constLanguage : 'english';
		var constMessage = this.options.constMessage ? this.options.constMessage : this.prefs.defaultMessage;
		var constSubmit = this.options.constSubmit ? this.options.constSubmit : this.prefs.defaultSubmit;
		var constControlPanel = this.options.constControlPanel ? this.options.constControlPanel : 'Launch Admin CP';
		var constAdminCP = this.options.constAdminCP ? this.options.constAdminCP : 'Admin CP';
		var constHistoryViewer = this.options.constHistoryViewer? this.options.constHistoryViewer : 'History Viewer';
		var constHistory = this.options.constHistory ? this.options.constHistory : 'History';
		var constLogin = this.options.constLogin ? this.options.constLogin : 'You must be logged in to use the shoutbox!';
		var smileys =
				'<img src="' + yPath + 'smileys/twisted.gif" onclick="javascript:smiley(\':twisted:\');" style="cursor: pointer;" /> ' +
				'<img src="' + yPath + 'smileys/cry.gif" onclick="javascript:smiley(\':cry:\');" style="cursor: pointer;" /> ' +
				'<img src="' + yPath + 'smileys/eek.gif" onclick="javascript:smiley(\':shock:\');" style="cursor: pointer;" /> ' +
				'<img src="' + yPath + 'smileys/evil.gif" onclick="javascript:smiley(\':evil:\');" style="cursor: pointer;" /> ' +
				'<img src="' + yPath + 'smileys/lol.gif" onclick="javascript:smiley(\':lol:\');" style="cursor: pointer;" /> ' +
				'<img src="' + yPath + 'smileys/mrgreen.gif" onclick="javascript:smiley(\':mrgreen:\');" style="cursor: pointer;" /> ' +
				'<img src="' + yPath + 'smileys/redface.gif" onclick="javascript:smiley(\':oops:\');" style="cursor: pointer;" /> ' +
				'<img src="' + yPath + 'smileys/rolleyes.gif" onclick="javascript:smiley(\':roll:\');" style="cursor: pointer;" /> ' +
				'<img src="' + yPath + 'smileys/confused.gif" onclick="javascript:smiley(\':?\');" style="cursor: pointer;" /> ' +
				'<img src="' + yPath + 'smileys/biggrin.gif" onclick="javascript:smiley(\':D\');" style="cursor: pointer;" /> ' +
				'<img src="' + yPath + 'smileys/cool.gif" onclick="javascript:smiley(\'8)\');" style="cursor: pointer;" /> ' +
				'<img src="' + yPath + 'smileys/mad.gif" onclick="javascript:smiley(\':x\');" style="cursor: pointer;" /> ' +
				'<img src="' + yPath + 'smileys/neutral.gif" onclick="javascript:smiley(\':|\');" style="cursor: pointer;" /> ' +
				'<img src="' + yPath + 'smileys/razz.gif" onclick="javascript:smiley(\':P\');" style="cursor: pointer;" /> ' +
				'<img src="' + yPath + 'smileys/sad.gif" onclick="javascript:smiley(\':(\');" style="cursor: pointer;" /> ' +
				'<img src="' + yPath + 'smileys/smile.gif" onclick="javascript:smiley(\':)\');" style="cursor: pointer;" /> ' +
				'<img src="' + yPath + 'smileys/surprised.gif" onclick="javascript:smiley(\':o\');" style="cursor: pointer;" /> ' +
				'<img src="' + yPath + 'smileys/wink.gif" onclick="javascript:smiley(\';)\');" style="cursor: pointer;" /><br />';
		var postForm =
			'<form id="ys-post-form"><fieldset>' +
				(inputUsername || this.prefs.allowGuests ? smileys : '') +
				(!inputUsername && this.prefs.allowGuests ? '<input id="ys-input-nickname" value="' + this.prefs.defaultNickname + '" type="text" maxlength="' + this.prefs.nicknameLength + '" class="ys-before-focus" />' : '<input id="ys-input-nickname" value="' + inputUsername + '" type="hidden" class="ys-before-focus" />') +
				'<input id="ys-input-uid" value="' + inputUID + '" type="hidden" />' +
				'<input id="ys-input-color" value="' + inputColor + '" type="hidden" />' +
				(inputUsername || this.prefs.allowGuests ? '<input id="ys-input-message" value="' + constMessage + '" type="text" maxlength="' + this.prefs.messageLength + '" class="ys-before-focus" />' : '') +
				(inputUsername || this.prefs.allowGuests ? '<input id="ys-input-submit" value="' + constSubmit + '" type="button" /><br />' : '') +
				(this.prefs.showCPLink ? '<a title="' + constControlPanel + '" id="ys-cp-launch" href="#">' + constAdminCP + '</a>' : '') +
				'<a title="' + constHistoryViewer + '" href="' + yPath + 'history.php?log=' + log + '&offset=' + timeOffset + '&language=' + constLanguage + '" target="_blank">' + constHistory + '</a>' +
				(!inputUsername && !this.prefs.allowGuests ? '<br />' + constLogin : '') +
			'</fieldset></form>';

		var postsDiv = '<div id="ys-posts"></div>';

		if (this.prefs.inverse) $('#yshout').html(postForm + postsDiv);
		else $('#yshout').html(postsDiv + postForm);

		var self = this;

		var defaults = {
			'ys-input-nickname': self.prefs.defaultNickname,
			'ys-input-message': constMessage
		};

		var keypress = function(e) {
			var key = window.event ? e.keyCode : e.which;
			if (key == 13 || key == 3) {
				self.send.apply(self);
				return false;
			}
		};

		var focus = function() {
			if (this.value == defaults[this.id])
				$(this).removeClass('ys-before-focus').val('');
		};

		var blur = function() {
			if (this.value == '')
				$(this).addClass('ys-before-focus').val(defaults[this.id]);
		};

		$('#ys-input-message').keypress(keypress).focus(focus).blur(blur);
		$('#ys-input-nickname').keypress(keypress).focus(focus).blur(blur);

		$('#ys-input-submit').click(function(){ self.send.apply(self) });
		$('#ys-post-form').submit(function(){ return false });
	},

	initRefresh: function() {
		var self = this;
		this.refreshTimer = setInterval(function() {
			self.ajax(self.updates, { reqType: 'refresh' });
		}, 4500);
	},

	initFlood: function() {
		var self = this;
		this.floodCount = 0;
		this.floodControl = false;

		this.floodTimer = setInterval(function() {
			self.floodCount = 0;
		}, this.prefs.floodTimeout);
	},

	initCP: function() {
		var self = this;

		$('#ys-cp-launch').click(function() {
			self.openCP.apply(self);
			return false;
		});
	},

	openCP: function(url) {
		var self = this;
		if (this.cpOpen) return;
		this.cpOpen = true;
		if (!url) url = this.options.yPath + 'admincp-sb.php';

		$('body').append('<div id="ys-cp-overlay"></div><div id="ys-cp"><a title="Close Admin CP" href="#" id="ys-cp-close">Close</a><object id="cp-browser" data="' + url +'" type="text/html">Something went horribly wrong.</object></div>');

		var scrollTop = this.scrollTop();

		if (scrollTop > 0)
			$('#ys-cp-overlay').css('margin-top', scrollTop + 'px');
			$('#cp-browser').css('margin-top', scrollTop + 'px');
			$('#ys-cp-close').css('margin-top',  scrollTop  - 290 + 'px');

		$('#ys-cp-overlay, #ys-cp-close').click(function() {
			self.reload.apply(self, [true]);
			self.closeCP.apply(self);
			return false;
		});
	},

	closeCP: function() {
		this.cpOpen = false;
		$('#ys-cp-overlay, #ys-cp').remove();
	},

	send: function() {

		if (!this.validate()) return;
		if (this.prefs.flood && this.floodControl) return;

		var  postNickname = $('#ys-input-nickname').val(), postUID = $('#ys-input-uid').val(), postColor = $('#ys-input-color').val(), postMessage = $('#ys-input-message').val();

		if (postMessage == '/cp')
			this.openCP();
		else
			this.ajax(this.updates, {
				reqType: 'post',
				nickname: postNickname,
				uid: postUID,
				color: postColor,
				message: postMessage
			});

		$('#ys-input-message').val('')

		if (this.prefs.flood) this.flood();
	},

	validate: function() {
		var nickname = $('#ys-input-nickname').val(),
				message = $('#ys-input-message').val(),
				error = false;

		var showInvalid = function(input) {
			$(input).removeClass('ys-input-valid').addClass('ys-input-invalid').get(0).focus();
			error = true;
		}

		var showValid = function(input) {
			$(input).removeClass('ys-input-invalid').addClass('ys-input-valid');
		}

		if (nickname == '' || nickname == this.prefs.defaultNickname)
			showInvalid('#ys-input-nickname');
		else
			showValid('#ys-input-nickname');

		var constMessage = this.options.constMessage ? this.options.constMessage : this.prefs.defaultMessage;
		if (message == '' || message == constMessage)
			showInvalid('#ys-input-message');
		else
			showValid('#ys-input-message');

		return !error;
	},

	flood: function() {
		var self = this;

		if (this.floodCount < this.prefs.floodMessages) {
			this.floodCount++;
			return;
		}

		this.disable();

		setTimeout(function() {
			self.floodCount = 0;
			self.enable.apply(self);
		}, this.prefs.floodDisable);
	},

	disable: function () {
		$('#ys-input-submit').get(0).disabled = true;
		this.floodControl = true;
	},

	enable: function () {
		$('#ys-input-submit').get(0).disabled = false;
		this.floodControl = false;
	},

	updates: function(updates) {
		if (!updates) return;

		if (updates.prefs) this.prefs = updates.prefs;
		if (updates.posts) this.posts(updates.posts);
	},

	posts: function(p) {
		for (var i = 0; i < p.length; i++)
			this.post(p[i]);

		this.truncate();
	},

	post: function(post) {
		var timeOffset = this.options.timeOffset ? this.options.timeOffset : '0';
		var pad = function(n) { return n > 9 ? n : '0' + n; };
		var date = function(ts) { return new Date((ts - timeOffset) * 1000); };
		var time = function(ts) {
			var d = date(ts);
			var h = d.getHours(), m = d.getMinutes();

			if (self.prefs.timestamp == 12) {
				h = (h > 12 ? h - 12 : h);
				if (h == 0) h = 12;
			}

			return pad(h) + ':' + pad(m);
		};

		var dateStr = function(ts) {
			var t = date(ts);

		  var Y = t.getFullYear();
		  var M = t.getMonth();
		  var D = t.getDay();
		  var d = t.getDate();
		  var day = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][D];
		  var mon = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
		             'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][M];

		  return day + ' ' + mon + '. ' + d + ', ' + Y;
		};

		var self = this;

		this.postNum++;

		var id = 'ys-post-' + this.postNum;
		post.message = this.censor(post.message);
		post.message = this.bbcodes(post.message);
		post.message = this.smileys(post.message);
		post.message = this.links(post.message);

		var userspec_xtra_html =
			post.admin ? ' ys-admin-post' : (
				post.donor ? ' ys-donor-post' :
					''
			);

		//OLD // '<div id="' + id + '" class="ys-post' + (post.admin ? ' ys-admin-post' : '') +  (post.donor ? ' ys-donor-post' : '') + (post.banned ? ' ys-banned-post' : '')

		var html =
			'<div id="' + id + '" class="ys-post' + userspec_xtra_html + (post.banned ? ' ys-banned-post' : '') + '">' +
				(this.prefs.timestamp > 0 ? '<span class="ys-post-timestamp">' + time(post.timestamp) + '</span> ' : '') +
				(post.uid != 1 ? '<span class="ys-post-nickname"><a href="userdetails.php?id=' + post.uid + '" style="border-bottom: none;' + (post.color ? ' color: ' + post.color + ';' : '') + '">' + post.nickname + '</a>:</span> ' : '<span class="ys-post-nickname"' + (post.color ? ' style="color: ' + post.color + ';"' : '') + '>' + post.nickname + ':</span> ') +
				'<span class="ys-post-message">' + post.message + '</span> ' +
				'<span class="ys-post-info' + (this.prefs.info == 'overlay' ? ' ys-info-overlay' : ' ys-info-inline') + '">' + (post.adminInfo ? '<em>IP:</em> ' + post.adminInfo.ip + ', ' : '') + '<em>Posted:</em> ' +  dateStr(post.timestamp) + '.</span>' +
				'<span class="ys-admin-actions"><a title="Show post information" class="ys-info-link" href="#">Info</a>'  + (post.adminInfo ? ' | ' + (post.banned ? '<a title="Unban ' + post.nickname + '" class="ys-unban-link" href="#">Unban</a>' :


				(
					'<a title="Ban ' + post.nickname + '" class="ys-ban-link" href="#">Ban</a>'
				+ '&nbsp;<a onmousemove="return false;" onmouseover="return false;" onmouseout="return false;"><select style="font-size:9px;" class="ys-ban-select" href="#"><option value="21600">6 godzin</option><option value="86400">1 dzien</option><option selected value="259200">3 dni</option><option value="604800">1 tydzien</option><option value="864000">10 dni</option><option value="1209600">2 tygodnie</option><option value="1814400">3 tygodnie</option><option value="2592000">1 miesiac</option><option value="7776000">3 miesiące</option><option value="31536000">1 rok</option></select></a>'
				)




			) : '') + '</span>' +
			'</div>';

		if (this.prefs.inverse) $('#ys-posts').prepend(html);
		else $('#ys-posts').append(html);

		$('#' + id + ' .ys-info-link').click(function() {
			if (this.innerHTML == 'Info') {
				$('#' + id + ' .ys-post-info').css('display', 'block');
				this.innerHTML = 'Close Info';
			} else {
				$('#' + id + ' .ys-post-info').css('display', 'none');
				this.innerHTML = 'Info';
			}

			return false;

		});

		$('#' + id + ' .ys-ban-select').change(function() {

			window.selectedBanLength = $(this).val();
			//alert(window.selectedBanLength);
			return true;

		});


		$('#' + id + ' .ys-ban-link').click(function() {
			if (this.innerHTML == 'Banning...') return;

			var pars = {
				reqType: 'ban',
				ip: post.adminInfo.ip,
				nick:	post.nickname,
				uid:	post.uid,
				time:	window.selectedBanLength ? selectedBanLength : 259200 //3 days is default bantime
			};

			self.ajax(function(json) {
				if (json.error) {
					switch(json.error) {
						case 'admin':
							self.error('You\'re not an admin. Log in through the admin CP to ban people.');
							break;
						case 'already':
							self.reload();
						//	self.error('That guy\'s banned already!');
							break;
					}

					return;
				}

				self.reload();
			}, pars);

			this.innerHTML = 'Banning...';
			return false;
		});



		$('#' + id + ' .ys-unban-link').click(function() {
			if (this.innerHTML == 'Unbanning...') return;

			var pars = {
				reqType: 'unban',
				ip: post.adminInfo.ip,
				nick:	post.nickname,
				uid:	post.uid
			};

			self.ajax(function(json) {
				if (json.error) {
					switch(json.error) {
						case 'admin':
							self.error('You\'re not an admin. Log in through the admin CP to ban people.');
							break;
						case 'already':
							self.reload();
						//	self.error('That guy\'s unbanned already!');
							break;
					}

					return;
				}

				self.reload();
			}, pars);

			this.innerHTML = 'Unbanning...';
			return false;
		});
	},

	censor: function(s) {
		var badwords = this.options.arrayBadwords ? this.options.arrayBadwords : new Array();
		for (var i = 0; i < badwords.length; ++i)
			s = s.replace(badwords[i], '*censored*');
		return s;
	},

	bbcodes: function(s) {
		s = s.replace(/\[b\]((\s|.)+?)\[\/b\]/, '<b>$1</b>');
		s = s.replace(/\[i\]((\s|.)+?)\[\/i\]/, '<i>$1</i>');
		s = s.replace(/\[u\]((\s|.)+?)\[\/u\]/, '<u>$1</u>');
		s = s.replace(/\[color=([a-zA-Z]+)\]((\s|.)+?)\[\/color\]/i, '<font color="$1">$2</font>');
		s = s.replace(/\[color=(#[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9])\]((\s|.)+?)\[\/color\]/i, '<font color="$1">$2</font>');
		s = s.replace(/\[size=([1-7])\]((\s|.)+?)\[\/size\]/i, '<font size="$1">$2</font>');
		s = s.replace(/\[font=([a-zA-Z ,]+)\]((\s|.)+?)\[\/font\]/i, '<font face="$1">$2</font>');
		return s;
	},

	smileys: function(s) {
		var yp = this.options.yPath;

		var smile = function(str, smiley, image) {
			return str.sReplace(smiley, '<img src="' + yp + 'smileys/' + image + '" />');
		};

		s = smile(s, ':twisted:',  'twisted.gif');
		s = smile(s, ':cry:',  'cry.gif');
		s = smile(s, ':shock:',  'eek.gif');
		s = smile(s, ':evil:',  'evil.gif');
		s = smile(s, ':lol:',  'lol.gif');
		s = smile(s, ':mrgreen:',  'mrgreen.gif');
		s = smile(s, ':oops:',  'redface.gif');
		s = smile(s, ':roll:',  'rolleyes.gif');

		s = smile(s, ':?',  'confused.gif');
		s = smile(s, ':D',  'biggrin.gif');
		s = smile(s, '8)',  'cool.gif');
		s = smile(s, ':x',  'mad.gif');
		s = smile(s, ':|',  'neutral.gif');
		s = smile(s, ':P',  'razz.gif');
		s = smile(s, ':(',  'sad.gif');
		s = smile(s, ':)',  'smile.gif');
		s = smile(s, ':o',  'surprised.gif');
		s = smile(s, ';)',  'wink.gif');

		return s;
	},

	links: function(s) {
		return s.replace(/((https|http|ftps|ftp|ed2k|irc):\/\/[\S]+)/gi, '<a href="$1" target="_blank">$1</a>');

	},

	truncate: function(clearAll) {
		var truncateTo = this.options.isLongVersion ?
			(clearAll ? 0 : this.prefs.truncate_long) :
				(clearAll ? 0 : this.prefs.truncate);


		var posts = $('div.ys-post').size();
		if (posts <= truncateTo) return;

		if (this.prefs.inverse)
			$('div.ys-post:gt(' + truncateTo + ')').remove();
		else
			$('div.ys-post:lt(' + (posts - truncateTo) + ')').remove();
	},

	reload: function(everything) {
		if (everything) {
			this.ajax(function(json) {
				$('#yshout').html('');
				clearInterval(this.refreshTimer);
				clearInterval(this.floodTimer);
				this.initialLoad(json);
			}, {
				reqType: 'init',
				yPath: this.options.yPath,
				log: this.options.log
			});
		} else {
			this.ajax(function(json) { this.truncate(true); this.updates(json); },{
				reqType: 'reload'
			});
		}
	},

	error: function(str) {
		alert(str);
	},

	json: function(parse) {
		this.d('In json: ' + parse);
		var json = eval('(' + parse + ')');
		if (!this.checkError(json))
            return json;
        return null;
	},

	checkError: function(json) {
		if (!json.yError) return false;

		this.d('Error: ' + json.yError);
		return true;
	},

	pageSize: function() {
		var de = document.documentElement;
		var w = window.innerWidth || (de && de.clientWidth) || document.body.clientWidth;
		var h = window.innerHeight || (de && de.clientHeight) || document.body.clientHeight;

		return [w, h];
	},

	scrollTop: function (){
		if (window.pageYOffset)	return window.pageYOffset;

		if (document.documentElement && document.documentElement.scrollTop)
		 return document.documentElement.scrollTop;

		if (document.body) return document.body.scrollTop;
	},

	ajax: function(callback, pars) {
		//alert(this.options.isLongVersion);
		pars = Object.extend({
			reqFor: 'shout',
			isLongVersion: this.options.isLongVersion
		}, pars);

		var self = this;

		$.post(this.options.yPath + 'index.php', pars, function(parse) {
            if (parse)
                callback.apply(self, [parse]);
            else
                callback.apply(self);
		});
	},

	d: function(message) {
		$('#debug').css('display', 'block').prepend('<p>' + message + '</p>');
	}
};
