function comments_init() {
	if (!document.getElementById('comments')) {
		return;
	}

	// apply the onsubmit functionality
	if (document.getElementById('comments').getElementsByTagName('form').length > 0) {
		document.getElementById('comments').getElementsByTagName('form')[0].onsubmit = comments_addComment;
	}

	// apply the deselect comment for reply functionality
	var oDeselectForReply = document.getElementById('deselect-for-reply');
	if (oDeselectForReply) {
		oDeselectForReply.style.display = 'none';
		oDeselectForReply.onclick = comments_deselectForReplyClick;
	}

	// apply the filter comments functionality
	var oCommentsSearchForm = document.getElementById('comments-search-form');
	if (oCommentsSearchForm) {
		oCommentsSearchForm.onsubmit = comments_searchComments;
	}

	// apply the onclick functionality to reply links
	oaSelectForReplyLinks = document.getElementById('comments').getElementsByClassName('select-for-reply');
	for (var i = 0; i < oaSelectForReplyLinks.length; i++) {
		oaSelectForReplyLinks[i].onclick = comments_selectForReplyClick;
	}

	comments_addPaginationItemClick(document.getElementById('comments').getElementsByClassName('pagination'));
}

function comments_addComment() {
	var form = this;
	var itemId = this.parentNode.className.match(/(^|\s+)c-(\d+)(\s+|$)/)[2];

	// validate
	if (!comments_isValid(form)) {
		return false;
	}

	// disable the submit button, change the text to 'SUBMITTING COMMENT...' and hide reCAPTCHA error message
	var oSubmitButton = document.getElementById('submit_comment');
	oSubmitButton.disabled = true;
	oSubmitButton.value = 'SUBMITTING COMMENT...';

	var oRecaptchaField = document.getElementById('recaptcha_input');
	if (oRecaptchaField) {
		oRecaptchaField.getElementsByClassName('error')[0].style.display = 'none';
	}

	// build the POST data
	var data = 'item_id=' + itemId +
		'&text=' + encodeURIComponent(this.text.value);


	// add name if exists
	if (this.name) {
		data +='&name=' + encodeURIComponent(this.name.value);
	}

	// and email if exists
	if (this.email) {
		data += '&email=' + encodeURIComponent(this.email.value);
	}

	// and link if exists
	if (this.link) {
		data += '&link=' + encodeURIComponent(this.link.value);
	}

	if (typeof(Recaptcha) != 'undefined') {
		data += '&recaptcha_challenge_field=' + encodeURIComponent(this.recaptcha_challenge_field.value) +
			'&recaptcha_response_field=' + encodeURIComponent(this.recaptcha_response_field.value);
	}

	if(window.parentCommentId) {
		data += '&parent_comment_id='+window.parentCommentId;
	}

	// open the XHR
	var xhr = new XMLHttpRequest('MSXML2.XMLHTTP.3.0');
	xhr.open('POST', window.serverConfigs.docRoot + '/comment_add/', true);

	// set the POST headers
	xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
	xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
	xhr.setRequestHeader('Content-length', data.length);
	xhr.setRequestHeader('Connection', 'close');

	// reload comments on success
	xhr.onreadystatechange = function () {
		if (xhr.readyState == 4) {
			var sIdOfElementToFocus = 'add-comment';
			if (xhr.status == 200) {
				switch (true) {
					case xhr.responseText.indexOf('SUCCESS') == 0:
						window.location.reload();
					break;
					case xhr.responseText.indexOf('INVALID_CAPTCHA') == 0:
						if (oRecaptchaField) {
							oRecaptchaField.getElementsByClassName('error')[0].style.display = 'inline';
						}
						sIdOfElementToFocus = 'recaptcha_response_field';
					break;
					case xhr.responseText.indexOf('INVALID_EMAIL') == 0:
						var oEmailError = document.getElementsByClassName('error email')[0].style.display = 'inline';
						sIdOfElementToFocus = 'email';
					break;
					case xhr.responseText.indexOf('INVALID_NAME') == 0:
						var oEmailError = document.getElementsByClassName('error name')[0].style.display = 'inline';
						sIdOfElementToFocus = 'name';
					break;
					case xhr.responseText.indexOf('INVALID_TEXT') == 0:
						var oEmailError = document.getElementsByClassName('error text')[0].style.display = 'inline';
						sIdOfElementToFocus = 'text';
					break;
				}
			} else{
				alert(window.serverConfigs.xhrError);
			}

			// after the request has finished (with success, invalid captcha or other error) refresh the captcha image
			if (typeof(Recaptcha) != 'undefined') {
				Recaptcha.destroy();
				Recaptcha.create(window.serverConfigs.recaptchaPublicKey, document.getElementById('recaptcha_widget'), RecaptchaOptions);
			}

			// enable the submit button, change the text to 'SUBMIT COMMENT', focus the desired element
			var oSubmitButton = document.getElementById('submit_comment');
			oSubmitButton.disabled = false;
			oSubmitButton.value = 'SUBMIT COMMENT';
			document.getElementById(sIdOfElementToFocus).focus();
		}
	}
	xhr.send(data);

	return false;
}

function comments_isValid(form) {
	// reset errors
	var oaErrors = form.getElementsByClassName('error');
	for (var i = 0; i < oaErrors.length; i++) {
		oaErrors[i].style.display = 'none';
	}

	// validate name
	if (form.name && !form.name.value.match(/^[\w_-][\s\w_-]*$/)) {
		document.getElementsByClassName('error name')[0].style.display = 'inline';
		document.getElementById('name').focus();
		return false;
	}

	// validate email
	if (form.email) {
		var iOccurencesCount = 0;
		for (var i = 0; i < form.email.value.length; i++) {
			if (form.email.value[i] == '@') {
				iOccurencesCount++;
			}
		}

		if (iOccurencesCount != 1) {
			document.getElementsByClassName('error email')[0].style.display = 'inline';
			document.getElementById('email').focus();
			return false;
		}
	}

	// validate text
	if (form.text && form.text.value.replace(/(^\s+|\s+$)/, '') == '') {
		document.getElementsByClassName('error text')[0].style.display = 'inline';
		document.getElementById('text').focus();
		return false;
	}

	return true;
}

function comments_searchComments() {
	// build the search terms array
	var sSearchTerms = document.getElementById('comments-search-text').value;
	var saSearchTerms = [ '' ];
	var saSearchTermsCount = 0;
	for (var i = 0; i  < sSearchTerms.length; i++) {
		if (sSearchTerms.charAt(i) == ' ' || sSearchTerms.charAt(i) == '.' || sSearchTerms.charAt(i) == ',' || sSearchTerms.charAt(i) == '?' || sSearchTerms.charAt(i) == '!' || sSearchTerms.charAt(i) == ':') {
			switch (true) {
				case saSearchTerms[saSearchTermsCount].length >= 3:
					saSearchTerms[++saSearchTermsCount] = '';
				break;
				case saSearchTerms[saSearchTermsCount].length > 0:
					saSearchTerms[saSearchTermsCount] = '';
				break;
			}
		} else {
			saSearchTerms[saSearchTermsCount] += sSearchTerms.charAt(i).toLowerCase();
		}
	}

	// remove the last search term if it exists and is invalid
	if (saSearchTerms[saSearchTerms.length - 1].length <= 2) {
		saSearchTerms.pop();
	}

	if (saSearchTerms.length > 0) {
		if (window.oaItemComments) {
			comments_filterComments(saSearchTerms);
		} else {
			var iItemId = document.getElementById('comments').className.match(/(^|\s+)c-(\d+)(\s+|$)/)[2];

			var xhr = new XMLHttpRequest('MSXML2.XMLHTTP.3.0');
			xhr.open('GET', window.serverConfigs.docRoot + '/comments/' + iItemId);

			// set the xhr request headers
			xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

			// display new text on success
			xhr.onreadystatechange = function () {
				if (xhr.readyState == 4) {
					if (xhr.status == 200) {
						window.oaItemComments = JSON.parse(xhr.responseText);
						comments_filterComments(saSearchTerms);
					} else{
						alert(window.serverConfigs.xhrError);
					}
				}
			}
			xhr.send(null);
		}
	} else {
		document.getElementById('filtered-comments').innerHTML = '';
		var oError = document.getElementById('comments-search-error');
		oError.innerHTML = 'Words shorter than 3 letters are neglected!';
		oError.style.display = 'inline';
	}

	return false;
}

function comments_selectForReplyClick() {
	// get selected comment id
	var commentId = window.parentCommentId = this.parentNode.parentNode.className.match(/(^|\s+)c-(\d+)(\s+|$)/)[2];

	// deselect all comments, except for the one that needs to be selected
	var oaComments = document.getElementById("comments").getElementsByClassName('comment');
	for (var i = 0; i < oaComments.length; i++) {
		if (oaComments[i].hasClassName('c-' + commentId)) {
			if (!oaComments[i].hasClassName('selected-for-reply')) {
				oaComments[i].className += ' selected-for-reply';
			}
		} else {
			oaComments[i].className = oaComments[i].className.replace(' selected-for-reply', '') ;
		}
	}

	// change the submit button text to 'SUBMIT AS REPLY' and show the 'deselect ...' link
	document.getElementById('submit_comment').value = 'SUBMIT AS REPLY';
	var oDeselectForReply = document.getElementById('deselect-for-reply');
	if (oDeselectForReply) {
		oDeselectForReply.style.display = 'inline';
	}

	return false;
}

function comments_deselectForReplyClick() {
	window.parentCommentId = 0;
	var oaComments = document.getElementById('comments').getElementsByClassName('comment');
	for (var i = 0; i < oaComments.length; i++) {
		oaComments[i].className = oaComments[i].className.replace(' selected-for-reply', '') ;
	}

	// change the submit button text back to simply 'send' and hide the 'deselect ...' link
	document.getElementById('submit_comment').value = 'SUBMIT COMMENT';
	var oDeselectForReply = document.getElementById('deselect-for-reply');
		if (oDeselectForReply) {
		oDeselectForReply.style.display = 'none';
	}

	return false;
}

function comments_filterComments(saSearchTerms) {
	// filter comments based on the search terms
	var oaFilteredComments = [];
	var iFilteredCommentsCount = 0;

	for (commentId in window.oaItemComments) {
		if (iFilteredCommentsCount == 20) {
			break;
		}

		for (var j = 0; j < saSearchTerms.length; j++) {
			if (window.oaItemComments[commentId].text.toLowerCase().indexOf(saSearchTerms[j]) > -1) {
				oaFilteredComments.push(window.oaItemComments[commentId]);
				break;
			} else {
				if (window.oaItemComments[commentId].children) {
					for (var childCommentId in window.oaItemComments[commentId].children) {
						if (window.oaItemComments[commentId].children[childCommentId].text.toLowerCase().indexOf(saSearchTerms[j]) > -1) {
							oaFilteredComments.push(window.oaItemComments[commentId]);
							break;
						}
					}
				}
			}
		}

		iFilteredCommentsCount++;
	}

	// if the search did not return any results, display a message
	var oError = document.getElementById('comments-search-error');
	if (oaFilteredComments.length == 0) {
		oError.innerHTML = 'Your search did not return any results!';
		oError.style.display = 'inline';
	} else {
		oError.innerHTML = '';
		oError.style.display = 'none';
	}

	// display the filtered search terms
	var oFilteredCommentsContainer = document.getElementById('filtered-comments');
	sHtml = '';

	for (var i = 0; i < oaFilteredComments.length; i++) {
		sHtml += '<div class="comment-with-author"><div class="comment-author">' + oaFilteredComments[i].name + '</div><div class="comment ' + (i % 2 == 0 ? 'even' : 'odd') + '"><div>' + oaFilteredComments[i].text;
		if (oaFilteredComments[i].children) {
			var j = 0;
			for (childCommentId in oaFilteredComments[i].children) {
				sHtml += '<div class="child-comment ' + (j % 2 == 0 ? 'odd' : 'even') + '"><div class="avatar"><div><img src="' + window.serverConfigs.docRoot + '/static/images/support.png" /></div>support</div><div class="text"><div>' + oaFilteredComments[i].children[childCommentId].text + '</div></div></div>';
				j++;
			}
		}
		sHtml += '</div><span class="posted-date">Posted ' + oaFilteredComments[i].created + '</span></div></div>';
	}

	oFilteredCommentsContainer.innerHTML = sHtml;
}

function comments_addPaginationItemClick(oCommentsPaginations) {
	for (var i = 0; i < oCommentsPaginations.length; i++) {
		var oaCommentsPaginationItems = oCommentsPaginations[i].getElementsByTagName('a');
		// set total number of pages
		oCommentsPaginations[i].className += ' cpt-'+(oaCommentsPaginationItems.length - 2);
		for (var j = 0; j < oaCommentsPaginationItems.length; j++) {
			oaCommentsPaginationItems[j].onclick = comments_paginationItemClick;
		}
	}
}

function comments_paginationItemClick() {
	var iClickedPage = parseInt(this.innerHTML.replace(/^(\s+|\s+)$/g, ''));

	var oaCommentsPaginationItems = this.parentNode.parentNode.getElementsByTagName('li');
	for (var i = 1; i < oaCommentsPaginationItems.length; i++) {
		if (oaCommentsPaginationItems[i].hasClassName('current')) {
			iCurrentPage = parseInt(oaCommentsPaginationItems[i].getElementsByTagName('a')[0].innerHTML);
			break;
		}
	}

	switch(true) {
		case iCurrentPage == iClickedPage:
			return false;
		break;
		case this.innerHTML.replace(/^(\s+|\s+)$/g, '') == window.serverConfigs.pagination.prev:
			comments_showCommentsPage(iCurrentPage - 1);
		break;
		case this.innerHTML.replace(/^(\s+|\s+)$/g, '') == window.serverConfigs.pagination.next:
			comments_showCommentsPage(iCurrentPage + 1);
		break;
		default:
			comments_showCommentsPage(iClickedPage);
		break;
	}

	return false;
}

function comments_showCommentsPage(iCommentsPage) {
	if (!window.commentPages) {
		window.commentPages = { };
	}

	if (!window.commentPages[iCommentsPage]) {
			var iItemId = document.getElementById('comments').className.match(/(^|\s+)c-(\d+)(\s+|$)/)[2];

			var oAjaxThrobbers = document.getElementById('comments').getElementsByClassName('ajax-throbber');
			for (var i = 0; i < oAjaxThrobbers.length; i++) {
				oAjaxThrobbers[i].style.display = 'block';
			}

			var xhr = new XMLHttpRequest('MSXML2.XMLHTTP.3.0');
			xhr.open('GET', window.serverConfigs.docRoot + '/comments_page/' + iItemId + '/' + iCommentsPage + '/');

			// set the xhr request headers
			xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

			// display new text on success
			xhr.onreadystatechange = function () {
				if (xhr.readyState == 4) {
					if (xhr.status == 200) {
						window.commentPages[iCommentsPage] = document.createElement('div');
						window.commentPages[iCommentsPage].className = 'comments-content';
						window.commentPages[iCommentsPage].innerHTML = xhr.responseText;

						// apply non w3c fixes to the newly created elements
						if (typeof(nonW3CFixes_init) != 'undefined') {
							window.commentPages[iCommentsPage].nonW3CFixes_init = nonW3CFixes_init;
							window.commentPages[iCommentsPage].nonW3CFixes_init();
						}

						// apply the onclick functionality to reply links
						oaSelectForReplyLinks = window.commentPages[iCommentsPage].getElementsByClassName('select-for-reply');
						for (var i = 0; i < oaSelectForReplyLinks.length; i++) {
							oaSelectForReplyLinks[i].onclick = comments_selectForReplyClick;
						}

						// apply the onclick functionality to pagination links
						comments_addPaginationItemClick(window.commentPages[iCommentsPage].getElementsByClassName('pagination'));

						for (var i = 0; i < oAjaxThrobbers.length; i++) {
							oAjaxThrobbers[i].style.display = 'none';
						}

						comments_updateCommentsPage(iCommentsPage);
					} else{
						alert(window.serverConfigs.xhrError);
					}
				}
			}
			xhr.send(null);
	} else {
		comments_updateCommentsPage(iCommentsPage);
	}
}

function comments_updateCommentsPage(iCommentsPage) {
	var oCommentsContent = document.getElementById('comments').getElementsByClassName('comments-content')[0];
	oCommentsContent.parentNode.replaceChild(window.commentPages[iCommentsPage], oCommentsContent);

	// highlight code bocks
	if (window.codeHighlighter) {
		window.codeHighlighter.highlight();
	}
}