var lastPage = 1;
var	currentId = 0;
var maskedElement = undefined;
var caret = 0;

function ajaxStatistics() {
	if (typeof ajaxStatisticsScript != 'undefined') {
		try {
			eval(ajaxStatisticsScript);
		}
		catch(e) {
		}
	}
}

/*
 * Block: forum list
 */

function goToPage(pageListNum, urlFmt) {
	Ext.MessageBox.show({
	title: getLabel('titleGoToPage'),
	msg: getLabel('labelGoToPage'),
	width: 300,
	buttons: { ok: getLabel('labelGoToPageBtn'), cancel: getLabel('labelCancelBtn') },
	prompt: true,
	fn: function(btn, text) { goToPage_submit(btn, text, urlFmt); }
});
}

function goToPage_submit(btn, page, urlFmt) {
	var pgNum = parseInt(page);
	if (pgNum) {
		document.location.href = String.format(urlFmt, pgNum);
	}
}

function extendThreadLife(threadId, forumId, getCodeUrl) {
	Ext.MessageBox.show({
	title: getLabel('titleExtendThreadLife'),
	msg: String.format(getLabel('labelExtendThreadLife'), getCodeUrl),
	width: 300,
	buttons: { ok: getLabel('labelSubmitCodeBtn'), cancel: getLabel('labelCancelBtn') },
	prompt: true,
	fn: function(btn, text) { extendThreadLife_submit(btn, text, threadId); }
});
}

function extendThreadLife_submit(btn, text, threadId) {
	if (btn == 'ok') {
		setWaitBox();
		Ext.Ajax.request({
			method: 'POST',
			url: 'action_threadlife.php',
			success: processXml,
			failure: doNothing,
			params: {
				threadId: threadId,
				code: text
			}
		});
	}
}

function timedAccessCode(forumId) {
	Ext.MessageBox.show({
	title: getLabel('titleTimedAccessCode'),
	msg: getLabel('labelTimedAccessCode'),
	width: 300,
	buttons: { ok: getLabel('labelSubmitCodeBtn'), cancel: getLabel('labelCancelBtn') },
	prompt: true,
	fn: function(btn, text) { timedAccessCode_submit(btn, text, forumId); }
});
}

function timedAccessCode_submit(btn, text, forumId) {
	if (btn == 'ok') {
		setWaitBox();
		Ext.Ajax.request({
			method: 'POST',
			url: 'action_timedaccess.php',
			success: processXml,
			failure: doNothing,
			params: {
				forumId: forumId,
				code: text
			}
		});
	}
}

/**
 * Changes group image from plus to minus and vice versa
 *
 * @param id JavaScript id of the group
 * @param nextImg Image to set
 * @param alt Text for "alt" attribute
 * @see toggleGroup
 */
function changeGroupImage(id, nextImg, alt) {
	var img = document.getElementById('collapser-' + id);
	var t = img.src.lastIndexOf('/');
	img.src = img.src.substr(0, t + 1) + nextImg + '.gif';
	img.alt = alt;
}

/**
 * Toggles group open state
 *
 * @param id JavaScript id of the group
 * @param groupId Real group ID
 * @param reload true if group content should be loaded from server
 * @see recordGroupStateChange
 * @see changeGroupImage
 */
function toggleGroup(id, groupId, reload) {
	var el = document.getElementById('cat-' + id + '-cnt');
	var state;
	if (el.style.display == '') {
		el.style.display = 'none';
		nextImg = 'plus';
		state = false;
		alt = getLabel('expandLabel');
	}
	else {
		el.style.display = '';
		nextImg = 'minus';
		state = true;
		alt = getLabel('collapseLabel');
	}
	if (reload) {
		if (typeof el.alreadyExpanded != 'undefined') {
			reload = false;
		}
		el.alreadyExpanded = 'yes';
	}
	changeGroupImage(id, nextImg, alt);
	document.getElementById('collapser-td-' + id).title = alt;
	recordGroupStateChange(id, groupId, state, reload);
}

/**
 * Records group state change in user properties on the server. Does this through AJAX call.
 *
 * @param int id JavaScript id for the group
 * @param int groupId GroupId
 * @param boolean state true, if group is expanded
 * @param boolean reload true, if group content should be reloaded from server
 * @see toggleGroup
 */
function recordGroupStateChange(id, groupId, state, reload) {
	if (reload) {
		setWaitBox();
	}
	Ext.Ajax.request({
		method: 'POST',
		url: 'action_groupstate.php',
		success: (reload ? processXml : doNothing),
		failure: doNothing,
		params: {
			action: (state ? 'expand' : 'collapse'),
			gid: groupId,
			reload: (reload ? '1' : '0'),
			cur: id,
			replace: 'cat-' + id + '-cnt-wait'
		}
	});
}

function submitPost() {
	if (document.messageForm) {
		setWaitBox();
		Ext.Ajax.request({
			method: 'POST',
			url: 'action_post.php',
			success: processXml,
			failure: errorMessage,
			params: {
				name: (document.messageForm.name ? document.messageForm.name.value : ''),
				subject: (document.messageForm.subject ? document.messageForm.subject.value : ''),
				messageText: isRTEEnabled() ? tinymce.EditorManager.get('messageText').getContent() : document.messageForm.messageText.value,
				code: document.messageForm.code ? document.messageForm.code.value : '',
				forumId: document.messageForm.forumId.value,
				parentId: document.messageForm.parentId.value,
				currentId: document.messageForm.currentId.value,
				rte: isRTEEnabled() ? 1 : 0
			}
		});
	}
	return false;
}

function putNick(nick) {
	tinymce.EditorManager.execCommand('mceInsertContent', false, '<b>' + nick + '</b><br><span id="caret' + caret + '"></span>');
	tinymce.EditorManager.execCommand('mceSelectNode', false, tinymce.EditorManager.get('messageText').getDoc().getElementById('caret' + caret));
	caret++;
}

function pasteSelection() {
	var userSelection = '';
	if (window.getSelection) {
		userSelection = window.getSelection();
	}
	else if (document.selection) {
		userSelection = document.selection.createRange().text;
	}
	else if (document.getSelection) {
		userSelection = document.getSelection();
	}
//	for (a in userSelection) {
//		alert(typeof a + ': ' + a);
//	}
	if (userSelection != '') {
		tinymce.EditorManager.execCommand('mceInsertContent', false, '<i>' + userSelection + '</i><br><span id="caret' + caret + '"></span>');
		tinymce.EditorManager.execCommand('mceSelectNode', false, tinymce.EditorManager.get('messageText').getDoc().getElementById('caret' + caret));
		caret++;
	}
}

function loginForm_submitHandler(form, event) {
	if (event.getKey() == event.ENTER) {
		form.getForm().submit();
	}
}

/**
 * Shows login form
 *
 * @param username Default login name to show in the form
 */
function loginForm(username) {
	Ext.onReady(function() {
		myform = new Ext.form.FormPanel({
			waitMsgTarget: document.body,
			labelAlign: 'left',
			buttonAlign: 'left',
			method: 'post',
			url: 'action_login.php',
			errorReader: new Ext.form.XmlErrorReader(),
			width: '100%',
			labelWidth: 100,
			items: [
				{
					xtype: 'hidden',
					name: 'actionType',
					value: 'login'
				},
				{
					xtype: 'textfield',
					name: 'login',
					id: 'login-name-field',
					fieldLabel: getLabel('labelLogin'),
					cls: 'login-field',
					emptyText: getLabel('labelEmptyLogin'),
					// No listener for "enter" key here because autosuggest will not work!
					maxLength: 80,
					minLength: 1,
					value: '',
					width: 120
				},
				{
					xtype: 'textfield',
					inputType: 'password',
					name: 'password',
					fieldLabel: getLabel('labelPassword'),
					cls: 'login-field',
					emptyText: '',
					id: 'login-password-field',
					listeners: {
						specialKey: function(field, event) { loginForm_submitHandler(myform, event); }
					},
					maxLength: 80,
					minLength: 3,
					value: '',
					width: 120
				},
				{
					xtype: 'checkbox',
					listeners: {
						specialKey: function(field, event) { loginForm_submitHandler(myform, event); }
					},
					name: 'remember',
					fieldLabel: getLabel('labelRemember'),
					cls: 'login-field'
				}
			]
		});

		myform.addButton({
			text: getLabel('submitLoginLabel'),
			handler: function() {
				myform.getForm().submit({
					url: 'action_login.php',
					waitMsg: getLabel('loginProcessingLabel')
				});
			}
		});

		if (username != '') {
			myform.getForm().setValues([
				{ id: 'login', value: username }
			]);
		}

		myform.on('actioncomplete', function() {
			setWaitBox();
			document.location.reload();
		});

		myform.on('actionfailed', function() {
			removeWaitBox();
			Ext.MessageBox.alert(getLabel('labelLoginFailed'), getLabel('messageLoginFailed'), function() {
				myform.getForm().findField('login').focus();
			});
		});

		myform.render('login');
		loginSuggestion();
	});
}

/**
 * Adds login suggestion combobox
 */
function loginSuggestion() {
	var ds = new Ext.data.Store({
		proxy: new Ext.data.HttpProxy({
			url: 'action_loginsuggest.php'
		}),
		reader: new Ext.data.JsonReader({
			root: 'results',
			totalProperty: 'total_results',
			id: 'name'
		}, [
			{ name: 'name' },
		])
	});

	// Custom rendering Template
	var resultTpl = new Ext.XTemplate(
		'<tpl for="."><div class="login-name-item">{name}</div></tpl>'
	);

	var combo = new Ext.form.ComboBox({
		applyTo: 'login-name-field',
		cls: 'login-field',
		displayField: 'name',
		emptyText: getLabel('labelEmptyLogin'),
		hideTrigger: true,
		id: 'login-suggest',
		itemSelector: 'div.login-name-item',
		listAlign: 'tr-br',
		listWidth: 180,
		loadingText: forumLabels.searching,
		minChars: 2,
		onSelect: function(record) {
			Ext.getCmp('login-name-field').setValue(record.data.name);
			Ext.getCmp('login-suggest').collapse();
			Ext.getCmp('login-password-field').focus(false, true);
		},
		pageSize: 10,
		tpl: resultTpl,
		typeAhead: false,
		store: ds
	});
}

/**
 * Creates logout form
 */
function logoutForm() {
	Ext.onReady(function() {
		myform = new Ext.form.FormPanel({
			waitMsgTarget: document.body,
			buttonAlign: 'left',
			method: 'POST',
			errorReader: new Ext.form.XmlErrorReader(),
			items: [
				{ xtype: 'hidden', name: 'actionType', value: 'logout' }
			],
			baseCls: '',
			url: 'action_login.php'
		});

		myform.addButton(getLabel('submitLogoutLabel'),
			function() {
				myform.getForm().submit({
					url: 'action_login.php',
					waitMsg: getLabel('logoutProcessingLabel')
				})
			}
		);

		myform.on('actioncomplete', function() {
			setWaitBox();
			document.cookie = 'phpf_user=;expires=' + (new Date(99999).toGMTString());
			document.location.reload();
		});

		myform.render('login');
	});
}

/**
 * Sets quick tip according to config
 *
 * @param config Configuration of the quick tip
 */
function setQuickTip(config) {
	Ext.onReady(function() {
		if (typeof config.length == 'undefined') {
			Ext.QuickTips.register({
				target: document.getElementById(config.id),
				trackMouse: true,
				text: config.message,
				title: config.title,
				animate: !Ext.isIE
			});
		}
		else {
			for (var i = 0; i < config.length; i++) {
				if ((typeof config[i] == 'object') && (typeof config[i].id != 'undefined')) {
					Ext.QuickTips.register({
						target: document.getElementById(config[i].id),
						trackMouse: true,
						text: config[i].message,
						title: config[i].title,
						animate: !Ext.isIE
					});
				}
			}
		}
	});
}

/* Favorites */

/**
 * Adds forum to favorites
 *
 * @param int id ID of the forum
 */
function addFavorite(id) {
	setWaitBox();
	Ext.Ajax.request({
		method: 'POST',
		url: 'action_favorites.php',
		success: processXml,
		failure: errorMessage,
		params: {
			action: 'add',
			id: id,
			replace: 'fav-link-' + id,
			add: 'cat-1-cnt-t'
		}
	});
}

/**
 * Removes forum from favorites
 *
 * @param int id ID of the forum
 */
function removeFavorite(id) {
	setWaitBox();
	Ext.Ajax.request({
		method: 'POST',
		url: 'action_favorites.php',
		success: processXml,
		failure: errorMessage,
		params: {
			action: 'remove',
			id: id,
			replace: 'fav-link-' + id,
			remove: 'frow-' + id
		}
	});
}

/**
 * Empty response handler
 *
 * @param o Response object
 */
function doNothing(o) {
	// Nothing
	removeWaitBox();
}


/**
 * Processes one element for processXml() function
 *
 * @param	object	element	Element from ajax xml
 */
function processXml_processElement(element) {
	var action = element.getAttribute('action');
	var id = element.getAttribute('id');
	var extEl;
	var	el = null;
	if (id) {
		extEl = Ext.get(id);
	}
	if (action == 'new') {
		if (extEl) {
			Ext.DomHelper.insertHtml('beforeEnd', extEl.dom, element.firstChild.data);
		}
	}
	else if (action == 'remove') {
		if (extEl) {
			extEl.remove();
		}
	}
	else if (action == 'replace') {
		if (extEl) {
			Ext.DomHelper.overwrite(id, element.firstChild.data);
			el = extEl.dom;
		}
	}
	else if (action == 'jumpToForum') {
		var forumId = parseInt(element.getAttribute('forumId'));
		if (forumId > 0) {
			var page = parseInt(element.getAttribute('page'));
			document.location.href = 'forum.php?id=' + forumId + (page ? '&page=' + page : '') + '&rnd=' + Math.random();
			return false;
		}
	}
	else if (action == 'jumpToThread') {
		var threadId = parseInt(element.getAttribute('threadId'));
		if (threadId > 0) {
			var page = parseInt(element.getAttribute('page'));
			var anchor = '';//element.getAttribute('anchor');
			document.location.href = 'thread.php?id=' + threadId + (page ? '&page=' + page : '') + '&rnd=' + Math.random() + (anchor ? '#' + anchor : '');
			return false;
		}
	}
	else if (action == 'setPage') {
		// TODO !!!
	}
	else if (action == 'reload') {
		document.location.reload();
	}
	else if (action == 'alert') {
		Ext.MessageBox.alert(getLabel('titleExtendThreadLife'), element.firstChild.data);
	}
	else {
		// Unknown action
		Ext.MessageBox.alert(getLabel('errorAlertTitle'), '[' + i + '] ' + getLabel('errorUnknownAction') + action);
	}
	if (el != null) {
		var scroll = element.getAttribute('scroll');
		if (scroll != null && parseInt(scroll) != 0) {
			var yPos = extEl.getY();
			if (yPos < Ext.getBody().getScroll().top) {
				window.scrollTo(0, yPos);
			}
		}
		var scripts = el.getElementsByTagName('script');
		if (typeof scripts.length != 'undefined') {
			for (var j = 0; j < scripts.length; j++) {
				eval(scripts[j].innerHTML);
			}
		}
	}
	ajaxStatistics();
	return true;
}

/**
 * Special processing for favorite forums inside processXml()
 */
function processXml_favorites() {
	var el = document.getElementById('cat-1-cnt-t');
	if (el) {
		if (el.rows.length == 0) {
			// No more rows in favorites, hide
			document.getElementById('ftr-a').style.display = 'none';
			document.getElementById('ftr-b').style.display = 'none';
		}
		else {
			// There are rows in favorites, hide
			document.getElementById('ftr-a').style.display = '';
			document.getElementById('ftr-b').style.display = '';
		}
	}
}

/**
 * Replaces content with one from response
 *
 * @param o Response object
 */
function processXml(o) {
	var i, removeWait = false;
	try {
		var xml = o.responseXML;
		var response = xml.getElementsByTagName('response')[0];
		if (response.getAttribute('success') == 'false') {
			removeWaitBox();
			Ext.MessageBox.alert(getLabel('errorAlertTitle'), response.firstChild.data);
			return;
		}
		else {
			var elements = xml.getElementsByTagName('element');
			for (i = 0; i < elements.length; i++) {
				removeWait |= processXml_processElement(elements[i]);
			}
		}
	} catch(e) {
		removeWaitBox();
		Ext.MessageBox.alert(getLabel('errorAlertTitle'), '[' + i + '/' + e.line + '] ' + e.message);
		//for (var i in e) alert(i + ' = ' + e[i]);
		if (typeof maskedElement != 'undefined') {
			maskedElement.unmask();
			maskedElement = undefined;
		}
		return;
	}
	processXml_favorites();
	if (removeWait) {
	removeWaitBox();
	}
}


/**
 * Shows error message on request error
 *
 * @param o Response object
 */
function errorMessage(o) {
	removeWaitBox();
	Ext.MessageBox.alert(getLabel('errorAlertTitle'), o.statusText);
}

/* Forum list */

/**
 * Switches forum to page
 *
 * @param int id ID of the forum
 * @param int page Page to switch to
 */
function showForumPage(id, page) {
	dhtmlHistory.add('page-' + page, id);
	setWaitBox();
	Ext.Ajax.request({
		method: 'POST',
		url: 'action_forumpage.php',
		success: function(o) {
			lastPage = page; processXml(o);
		},
		failure: errorMessage,
		params: {
			action: 'forumPage',
			id: id,
			replace: 'forum-content',
			page: page
		}
	});
}

/**
 * Callback for DHTML history for forums
 *
 * @param newLocation Location to set
 * @param historyData History data (query string)
 */
function handleHistoryChange_forum(newLocation, historyData) {
	var i = newLocation.indexOf('-') + 1;
	if (i > 0) {
		var page = parseInt(newLocation.substr(i));
		if (historyData == null) {
			i = document.location.search.indexOf('id=');
			if (i >= 0) {
				historyData = parseInt(document.location.search.substr(i + 3));
			}
		}
		if (page != lastPage) {
			showForumPage(historyData, page);
		}
	}
	else {
		history.go(-1);
	}
}

/**
 * Initializes DHTML history for forums
 */
function initHistory_forum() {
	if (dhtmlHistory.isFirstLoad()) {
		var i = document.location.search.indexOf('page='), page = 0, qpage = 1;
		if (i >= 0) {
			qpage = parseInt(document.location.search.substr(i+5));
		}
		i = document.location.hash.indexOf('#page-');
		if (i >= 0) {
			// only if have ajax part
			page = parseInt(document.location.hash.substr(i+6));
		}
		i = document.location.search.indexOf('id=');
		var id = parseInt(document.location.search.substr(i + 3));
		if (page > 0 && page != qpage) {
			showForumPage(id, page);
		}
		else {
			dhtmlHistory.add('page-' + (page ? page : qpage), id);
		}
	}
}

/* Message list (single thread) */

function reportMessage_submit(btn, text, messageId) {
	text = trim(text);
	if (btn == 'ok' && text != '') {
		setWaitBox();
		Ext.Ajax.request({
			method: 'POST',
			url: 'action_report.php',
			success: function(o) {
				removeWaitBox();
				Ext.MessageBox.alert(getLabel('labelThankYou'), getLabel('labelReported'));
				var xml = o.responseXML;
				var elements = xml.getElementsByTagName('element');
				if (elements && elements.length > 0) {
					setWaitBox();
					processXml(o);
				}
			},
			failure: errorMessage,
			params: {
				messageId: messageId,
				text: text,
				replace: 'thread-content',
				page: lastPage
			}
		});
	}
}

function reportMessage(messageId) {
	Ext.MessageBox.show({
		title: getLabel('titleReportMessage'),
		msg: getLabel('labelReportMessage'),
		width: 300,
		buttons: { ok: getLabel('labelReportBtn'), cancel: getLabel('labelCancelBtn') },
		multiline: true,
		fn: function(btn, text) { reportMessage_submit(btn, text, messageId); },
		animEl: 'report-' + messageId
	});
}

function deleteWarning(warningId) {
	Ext.MessageBox.confirm(getLabel('titleDeleteWarning'), getLabel('labelDeleteWarning'),
		function(btn) {
			if (btn == 'yes') {
				setWaitBox();
				Ext.Ajax.request({
					method: 'POST',
					url: 'action_report.php',
					success: processXml,
					failure: errorMessage,
					params: {
						warningId: warningId,
						replace: 'thread-content',
						page: lastPage
					}
				});
			}
		}
	);
}

function openCloseThread(threadId, isClose) {
	var label = getLabel(!isClose ? 'labelCloseThread' : 'labelOpenThread');
	var labelStyle = 'width: 180px;';
	var form = new Ext.form.FormPanel({
		border: false,
		labelWidth: 160,
		footer: true,
		items: [
			{
				xtype: 'hidden',
				name: 'id',
				value: threadId
			},
			{
				xtype: 'textfield',
				name: 'closeReason',
				labelStyle: labelStyle,
				fieldLabel: getLabel('labelCloseOpenReason'),
				width: 300
			},
			{
				xtype: 'checkbox',
				name: 'notify',
				labelStyle: labelStyle,
				fieldLabel: getLabel('labelNotify')
			}
		]
	});
	var win = new Ext.Window({
		bodyStyle: 'padding: 5px 5px 0 5px',
		buttons: [
			{
				text: label,
				handler: function() {
					// Send ajax request
					setWaitBox();
					Ext.Ajax.request({
						method: 'POST',
						url: 'action_close.php',
						success: processXml,
						failure: errorMessage,
						params: form.getForm().getValues()
					});
					win.hide();
				}
			},
			{
				text: getLabel('labelCancelBtn'),
				handler: function() {
					win.close();
				}
			}
		],
		defaultButton: 0,
		items: form,
		modal: true,
		title: label,
		width: 520
	});
	win.show();
}

function moveThread(threadId, forumId) {
	var labelStyle = 'width: 180px;';
	var recDef = Ext.data.Record.create([
		{ name: 'id' },
		{ name: 'title' }
	]);
	var store = new Ext.data.Store({
		proxy: new Ext.data.HttpProxy({
			url: 'action_movethread.php?action=list&exclude=' + forumId,
			method: 'GET'
		}),
		reader: new Ext.data.JsonReader({
			totalProperty: 'count',
			root: 'forums',
			id: 'id'
		}, recDef),
		sortInfo: {
			field: 'title',
			direction: 'ASC'
		}
	});
	setWaitBox();
	store.load({
		callback: function(r, options, success) {
			var form = new Ext.form.FormPanel({
				border: false,
				labelWidth: 160,
				footer: true,
				items: [
					{
						xtype: 'hidden',
						name: 'threadId',
						value: threadId
					},
					{
						xtype: 'hidden',
						name: 'action',
						value: 'move'
					},
					new Ext.form.ComboBox({
						store: store,
						displayField: 'title',
						hiddenName: 'forumId',
						typeAhead: true,
						minChars: 0,
						mode: 'local',
						name: 'forumId_',
						triggerAction: 'all',
						emptyText: getLabel('labelSelectForum'),
						selectOnFocus: true,
						valueField: 'id',
						labelStyle: labelStyle,
						fieldLabel: getLabel('labelSelectForum'),
						width: 300
					}),
					{
						xtype: 'checkbox',
						name: 'notify',
						labelStyle: labelStyle,
						fieldLabel: getLabel('labelNotify')
					},
					{
						xtype: 'textarea',
						name: 'notifyText',
						labelStyle: labelStyle,
						fieldLabel: getLabel('labelNotifyText'),
						grow: true,
						growMax: 450,
						width: 300
					}
				]
			});
			var win = new Ext.Window({
				bodyStyle: 'padding: 5px 5px 0 5px',
				buttons: [
					{
						text: getLabel('labelMoveBtn'),
						handler: function() {
							// Send ajax request
							setWaitBox();
							Ext.Ajax.request({
								method: 'POST',
								url: 'action_movethread.php',
								success: function(o) {
									var xml = o.responseXML;
									var response = xml.getElementsByTagName('response')[0];
									if (response.getAttribute('success') == 'success') {
										removeWaitBox();
										Ext.MessageBox.alert(getLabel('labelMoveWindowTitle'), getLabel('labelMovedSuccessfully'), function() {
											setWaitBox();
											processXml(o);
										});
									}
									else {
										processXml(o);
									}
								},
								failure: errorMessage,
								params: form.getForm().getValues()
							});
							win.hide();
						}
					},
					{
						text: getLabel('labelCancelBtn'),
						handler: function() {
							win.hide();
						}
					}
				],
				defaultButton: 0,
				items: form,
				modal: true,
				title: getLabel('labelMoveWindowTitle'),
				width: 520
			});
			removeWaitBox();
			win.show();
		}
	});
}

/**
 * Switches topic to page
 *
 * @param int id ID of the forum
 * @param int page Page to switch to
 */
function showThreadPage(id, page) {
	dhtmlHistory.add('page-' + page, id);
	setWaitBox();
	Ext.Ajax.request({
		method: 'POST',
		url: 'action_threadpage.php',
		success: function(o) {
			lastPage = page; processXml(o);
		},
		failure: errorMessage,
		params: {
			action: 'threadPage',
			id: id,
			replace: 'thread-content',
			page: page
		}
	});
}

/**
 * Pins/unpins thread.
 *
 * @param	id	Thread ID to pin/unpin
 */
function pinThread(id) {
	setWaitBox();
	Ext.Ajax.request({
		method: 'POST',
		url: 'action_pin.php',
		success: processXml,
		failure: errorMessage,
		params: {
			id: id,
			replace: 'thread-content',
			page: lastPage
		}
	});
}

/**
 * Shows information about registered user
 *
 * @param string name User name
 */
function info(name) {
	alert(name);
}

/* Message editing functions */

var editingId = undefined;
var originalText = undefined;

function editPost_cancel() {
	// TODO Ckeck if modified and prompt to save
	var subjectEl = Ext.get('msg-subject-editor');
	if (subjectEl) {
		subjectEl.remove();
	}
	Ext.get('msg-content-' + editingId).dom.innerHTML = originalText;
	/** @type Ext.Element */
	var el = Ext.get('edit-ctrls-' + editingId);
	el.enableDisplayMode();
	el.hide(false);
	tinymce.EditorManager.execCommand('mceRemoveControl', false, 'msg-content-' + editingId);
	editingId = undefined;
	originalText = undefined;
}

function editPost_save() {
	setWaitBox();
	var	content = tinymce.EditorManager.get('msg-content-' + editingId).getContent();
	var subjectEl = Ext.get('msg-subject-editor');
	var subject = '';
	if (subjectEl) {
		subject = subjectEl.dom.value;
		subjectEl.remove();
	}
	Ext.Ajax.request({
		method: 'POST',
		url: 'action_edit.php',
		success: editPost_save_analyzeResult,
		failure: errorMessage,
		params: {
			id: editingId,
			action: 'edit',
			content: content,
			subject: subject,
			bbcode: 0
		}
	});
}

function editPost_save_analyzeResult(o) {
	var result = eval('(' + o.responseText + ')');
	if (result.success) {
		/** @type Ext.Element */
		var el = Ext.get('edit-ctrls-' + editingId);
		el.hide(false);
		tinymce.EditorManager.execCommand('mceRemoveControl', false, 'msg-content-' + editingId);
		Ext.get('msg-content-' + editingId).dom.innerHTML = result.content;
		if (typeof result.subject != 'undefined' && result.subject != '') {
			Ext.get('thread-subject').dom.innerHTML = result.subject;
		}
		editingId = undefined;
		originalText = undefined;
		removeWaitBox();
	}
	else {
		removeWaitBox();
		Ext.MessageBox.alert(getLabel('labelEditMessage'), result.error);
		// Keep editor
	}
	ajaxStatistics();
}

/**
 * Shows editor to edit message
 *
 * @param int id Message id
 */
function editPost_showEditor(id, isThread) {
	if (isThread) {
		var subjectEl = Ext.get('msg-subject-ph');
		subjectEl.createChild({
			tag: 'input',
			type: 'text',
			id: 'msg-subject-editor',
			value: Ext.get('thread-subject').dom.innerHTML
		});
	}
	/** @type Ext.Element */
	var el1 =  Ext.get('msg-content-' + id);
	originalText = el1.dom.innerHTML;
	tinymce.EditorManager.settings.width = '100%';
	tinymce.EditorManager.settings.height = Math.max(200, el1.getHeight());
	tinymce.EditorManager.execCommand('mceAddControl', true, 'msg-content-' + id);
	editingId = id;
	/** @type Ext.Element */
	var el2 = Ext.get('edit-ctrls-' + editingId);
	el2.enableDisplayMode();
	el2.show(false);
}

/**
 * Analyzes result of access check. Either shows error mesage or opens editor.
 *
 * @param	XHTTPRequest	o	Information about response
 * @param	int	id	Message ID
 */
function editPost_analyzeResult(o, id, isThread) {
	var result = eval('(' + o.responseText + ')');
	removeWaitBox();
	if (result.success && result.access) {
		editPost_showEditor(id, isThread);
	}
	else {
		Ext.MessageBox.alert(getLabel('labelEditMessage'), result.error);
	}
	ajaxStatistics();
}

function editPost(id, isThread) {
	if (typeof editingId != 'undefined') {
		if (editingId != id) {
			Ext.MessageBox.alert(getLabel('labelEditMessage'), getLabel('labelAnotherEditorActive'));
		}
	}
	else {
		setWaitBox();
		Ext.Ajax.request({
			method: 'POST',
			url: 'action_edit.php',
			success: function(o) {
				editPost_analyzeResult(o, id, isThread);
			},
			failure: errorMessage,
			params: {
				id: id,
				action: 'access'
			}
		});
	}
}

/**
 * Deletes post
 *
 * @param int id Message id
 */
function deletePost(id, page, isModerator) {
	var label = getLabel(id == currentId ? 'deleteThreadLabel' : 'deleteMessageLabel');
	if (!isModerator) {
		Ext.MessageBox.confirm(getLabel('deleteLabel'), getLabel(id == currentId ? 'deleteThreadLabel' : 'deleteMessageLabel'),
			function(btn) {
				if (btn == 'yes') {
					setWaitBox();
					Ext.Ajax.request({
						method: 'POST',
						url: 'action_deletemessage.php',
						success: processXml,
						failure: errorMessage,
						params: {
							id: id,
							replace: 'thread-content',
							page: lastPage
						}
					});
				}
			}
		);
	}
	else {
		// Moderator
		var labelStyle = 'width: 180px;';
		var form = new Ext.form.FormPanel({
			border: false,
			labelWidth: 160,
			footer: true,
			items: [
				{
					xtype: 'hidden',
					name: 'id',
					value: id
				},
				{
					xtype: 'hidden',
					name: 'replace',
					value: 'thread-content'
				},
				{
					xtype: 'hidden',
					name: 'page',
					value: lastPage
				},
				{
					xtype: 'checkbox',
					name: 'notify',
					labelStyle: labelStyle,
					fieldLabel: getLabel('labelNotify')
				},
				{
					xtype: 'textarea',
					name: 'notifyText',
					labelStyle: labelStyle,
					fieldLabel: getLabel('labelNotifyText'),
					grow: true,
					growMax: 450,
					width: 300
				}
			]
		});
		var win = new Ext.Window({
			bodyStyle: 'padding: 5px 5px 0 5px',
			buttons: [
				{
					text: label,
					handler: function() {
						// Send ajax request
						setWaitBox();
						Ext.Ajax.request({
							method: 'POST',
							url: 'action_deletemessage.php',
							success: processXml,
							failure: errorMessage,
							params: form.getForm().getValues()
						});
						win.hide();
					}
				},
				{
					text: getLabel('labelCancelBtn'),
					handler: function() {
						win.hide();
					}
				}
			],
			defaultButton: 0,
			items: form,
			modal: true,
			title: label,
			width: 520
		});
		win.show();
	}
}

function showIp_result(responseObj) {
	var gridWidth = 415;
	var hasExtInfo = (typeof responseObj.info.matches != 'undefined');
	var store1 = new Ext.data.JsonStore({
		root: 'ip',
		fields: [ 'ip', 'host', 'country', 'city']
	});
	store1.loadData(responseObj.info);
	var grid1 = new Ext.grid.GridPanel({
		store: store1,
		columns: [
			{ header: getLabel('labelIpIp'), width: 125, sortable: false, dataIndex: 'ip' },
			{ id: 'host', header: getLabel('labelIpHost'), width: 125, sortable: false, dataIndex: 'host' },
			{ header: getLabel('labelIpCountry'), width: 75, sortable: false, dataIndex: 'country'},
			{ header: getLabel('labelIpCity'), width: 75, sortable: false, dataIndex: 'city'}
		],
		stripeRows: true,
		autoExpandColumn: 'host',
		height: hasExtInfo ? 75 : 150,
		width: gridWidth
	});
	if (hasExtInfo) {
		// Matched users
		var store2 = new Ext.data.JsonStore({
			root: 'match_counters',
			fields: [ 'name', 'counter' ]
		});
		store2.loadData(responseObj.info);
		store2.sort('counter', 'DESC');
		var grid2 = new Ext.grid.GridPanel({
			store: store2,
			columns: [
				{ id: 'name', header: 'Name', width: 150, sortable: true, dataIndex: 'name' },
				{ header: 'Count', width: 75, sortable: true, dataIndex: 'counter' }
			],
			stripeRows: true,
			autoExpandColumn: 'name',
			height: 100,
			width: gridWidth
		});
		// Match details
		var store3 = new Ext.data.JsonStore({
			root: 'matches',
			fields: [ 'loginName', 'method', 'value' ]
		});
		store3.loadData(responseObj.info);
		var grid3 = new Ext.grid.GridPanel({
			store: store3,
			columns: [
				{ id: 'loginName', header: 'Name', width: 150, sortable: true, dataIndex: 'loginName' },
				{ header: 'Method', width: 75, sortable: true, dataIndex: 'method' },
				{ header: 'Value', width: 150, sortable: false, dataIndex: 'value' }
			],
			stripeRows: true,
			autoExpandColumn: 'loginName',
			height: 100,
			width: gridWidth
		});
		items = [{
				xtype: 'textfield',
				fieldLabel: getLabel('labelIpUserAgent'),
				readOnly: true,
				value: responseObj.info.ua,
				width: 322
			}, {
				xtype: 'fieldset',
				//checkboxToggle: true,
				collapsible: true,
				title: getLabel('labelIpSectionTitle'),
				autoHeight: true,
				items: grid1
			},{
				xtype: 'fieldset',
				//checkboxToggle: true,
				collapsible: true,
				title: 'match statistics',
				autoHeight: true,
				items: grid2
			},{
				xtype: 'fieldset',
				//checkboxToggle: true,
				collapsible: true,
				title: 'matching users',
				autoHeight: true,
				collapsed: true,
				items: grid3
		}];
	}
	else {
		items = grid1;
	}
	var form = new Ext.FormPanel({
		items: items
	});
	removeWaitBox();
	var win = new Ext.Window({
		bodyStyle: 'padding: 5px 5px 0 5px; font-size: 10px;',
		buttons: [
			{
				text: 'close',
				handler: function() {
					win.hide();
				}
			}
		],
		defaultButton: 0,
		items: form,
		modal: true,
		title: getLabel('labelIpWindowTitle') + ': ' + responseObj.info.user,
		width: gridWidth + 50,
		autoHeight: true
	});
	win.show();
}

function showIp_continue(o) {
	var	responseObj;
	try {
		responseObj = eval('(' + o.responseText + ')');
	}
	catch(e) {
		removeWaitBox();
		Ext.MessageBox.alert(getLabel('errorAlertTitle'), '[' + i + '] ' + e.message);
		return;
	}
	if (!responseObj.success) {
		removeWaitBox();
		Ext.MessageBox.alert(getLabel('errorAlertTitle'), responseObj.error);
	}
	else {
		showIp_result(responseObj);
	}
	ajaxStatistics();
}

/**
 * Shows IP for the
 *
 * @param int id Message id
 */
function showIp(id) {
	setWaitBox();
	Ext.Ajax.request({
		method: 'POST',
		url: 'action_ip.php',
		success: showIp_continue,
		failure: errorMessage,
		params: {
			id: id
		}
	});
}

/**
 * Callback for DHTML history for topics
 *
 * @param newLocation Location to set
 * @param historyData History data (query string)
 */
function handleHistoryChange_thread(newLocation, historyData) {
	var i = newLocation.indexOf('-') + 1;
	if (i > 0) {
		var page = parseInt(newLocation.substr(i));
		if (page != lastPage) {
			lastPage = page;
			var id = (historyData != null ? historyData : currentId);
			showThreadPage(id, page);
		}
	}
	else {
		history.go(-1);
	}
}

/**
 * Initializes DHTML history for threads
 */
function initHistory_thread() {
	if (dhtmlHistory.isFirstLoad()) {
		// Need to check if current page does not match anchor
		var i = document.location.hash.indexOf('#page-');
		if (i == 0) {
			var page = parseInt(document.location.hash.substr(6));
			if (page != lastPage) {
				// Need to jump
				handleHistoryChange_thread('page-' + page, currentId);
				return;
			}
		}
		dhtmlHistory.add('page-' + lastPage, currentId);
	}
}

// Utility

/**
 * Retrieves label text
 *
 * @param id ID of the label
 */
function getLabel(id) {
	if (typeof jsLabels != 'undefined') {
		for (i = 0; i < jsLabels.length; i++) {
			if (jsLabels[i].id == id) {
				return jsLabels[i].text;
			}
		}
	}
	return 'undef id=' + id;
}

/**
 * Shows wait box
 *
 * @param labelText Label text
 * @param labelTitle Message text
 */
function setWaitBox() {
	if (typeof maskedElement == 'undefined') {
		maskedElement = Ext.get(document.body);
		maskedElement.mask(getLabel('labelWaitTitle'), 'x-mask-loading');
	}
}

/**
 * Removes wait box
 */
function removeWaitBox() {
	if (typeof maskedElement != 'undefined') {
		maskedElement.unmask();
		maskedElement = undefined;
	}
}

// Startup


// A reusable error reader class for XML forms
Ext.form.XmlErrorReader = function(){
	Ext.form.XmlErrorReader.superclass.constructor.call(this, {
			record : 'field',
			success: '@success'
		}, [
			'id', 'msg'
		]
	);
};

Ext.extend(Ext.form.XmlErrorReader, Ext.data.XmlReader);

function dhtmlHistory_getParams() {
	// Page
	var i = document.location.search.indexOf('page=');
	if (i >= 0) {
		lastPage = parseInt(document.location.search.substr(i+5));
	}
	// ID
	i = document.location.search.indexOf('id=');
	if (i >= 0) {
		currentId = parseInt(document.location.search.substr(i + 3));
	}
}

function beingIdle() {
	Ext.Ajax.request({
		method: 'POST',
		url: 'action_idle.php',
		success: function() { },
		failure: function() { }
	});
}

function isRTEEnabled() {
	return (typeof(tinymce) != 'undefined');
}

Ext.onReady(function() {
	Ext.BLANK_IMAGE_URL = 'extlib/extjs/resources/images/default/s.gif';
	Ext.QuickTips.init();
	if (typeof dhtmlHistory_updateFunction == 'function') {
		dhtmlHistory_getParams();
		// Initialize framework
		dhtmlHistory.initialize();
		if (typeof dhtmlHistory_initFunction == 'function') {
			dhtmlHistory_initFunction();
		}
		dhtmlHistory.addListener(dhtmlHistory_updateFunction);
	}
	initToolbar();
	// Increase Ajax timeout
	Ext.Ajax.timeout = 60000;
	setInterval('beingIdle()', 4*60*1000);

	mailNotify();
});

function trim(s) {
	return s.replace(/^\s+|\s+$/g, '');
}

