(function($)
{

var Comment = window.Comment = function Comment(pageId, location, publicKey, showCaptcha, maxChars) {
	this.g_direction = "asc" ;
	this.g_orderBy = "created";
	this.pageId = pageId;
	this.parentComment = null;
	this.maxText = maxChars;
	this.location = location;
	this.lastReply = null;
	this.captchaPublicKey = publicKey;
	this.showCaptcha = showCaptcha;

	this.lastSearchObj = null;
	this.lastSearchTime = null;
}

Comment.prototype.onCommentBodyChange = function(oldValue)
{
	// Reset our search object;
	this.completeQuery();

	var txtCommentBody = document.getElementById("comment-body");


	var diff = this.maxText - txtCommentBody.value.length;

	if( diff <= 0 )
	{
		diff = 0;
		txtCommentBody.value = txtCommentBody.value.substr(0, maxText );
	}

	document.getElementById("comment-body-count").innerHTML = diff;

};

Comment.prototype.orderBy = function(orderBy, direction) {

	// Alias for jQuery post below.
	commentObj = this;

	if(orderBy.length == 0)
	{
		orderBy = this.g_orderBy;
	}
	else
	{
		this.g_orderBy = orderBy;
	}

	if(direction.length == 0)
	{
		orderBy = this.g_direction;
	}
	else
	{
		this.g_direction = direction;
	}

	searchObj = {
		'id' : this.pageId,
		'showcomment': true,
		'orderBy' : orderBy,
		'direction' : direction	};

 	// Set our last search obj for future reference
 	this.lastSearchObj = searchObj;
 	this.lastSearchTime = new Date();

	jQuery.post(
		this.location,
		searchObj,
		function(data) {
			commentObj.onShowComment(searchObj,data);
		},"html");
};

Comment.prototype.onShowComment = function(searchObj, data)
{
	// Reset our search object
	this.completeQuery();

	/* move our form out of the comment tree
	so that the replacement doesn't kill it */
	replyForm = jQuery("#comment-post-form");
	replyHeader = jQuery("#comment-header");
	replyHeader.after(replyForm);
	replyForm.hide();

	parentList = jQuery("#comment-container");
	commentNode = jQuery(data);

	parentList.replaceWith(commentNode);
};

Comment.prototype.saveComment = function( subject, body, parentComment )
{
	// Alias for jQuery post below.
	commentObj = this;

	// Fetch some additional fields for captcha.
	if(this.showCaptcha) {
		recapChallenge = jQuery("#recaptcha_challenge_field").val();
		recapResponse = jQuery("#recaptcha_response_field").val();
	}
	else
	{
		recapResponse	= "";
		recapChallenge	= "";
	}


	searchObj = {
		'id' : this.pageId,
		'savecomment': true,
		'subject' : subject,
		'body' : body,
		'recaptcha_challenge_field' : recapChallenge,
		'recaptcha_response_field' : recapResponse,
		'parent_comment': parentComment	};

	// Clear previous errors.
	this.clearError();

	jQuery.post(
		this.location,
		searchObj,
		function(data) {
			commentObj.onCommentSaved(searchObj,data);
	},"html");

};

Comment.prototype.deleteComment = function (deletecomment)
{
	if(confirm("Are you sure you want to delete the comment?")){
		/* move our form out of the comment tree
		so that the replacement doesn't kill it */
		replyForm = jQuery("#comment-post-form");
		replyHeader = jQuery("#comment-header");
		replyHeader.after(replyForm);
		replyForm.hide();

		var commentObj = this;
		searchObj = {
			'deletecomment' : deletecomment
		};

		// Simple double submission check
		currTime = new Date();
		if( (this.lastSearchObj == null) ||
			( (this.lastSearchObj) &&
			  (this.lastSearchObj['deletecomment'] != searchObj.deletecomment) &&
			  (this.lastSearchTime < currTime.getTime() - 1000) )
			)
		{
			// On success, lets delete the comment
			jQuery.post(
				this.location,
				searchObj,
				function(data) {
					commentObj.onCommentDelete(searchObj,data);
		 		} , "html" );
		}
		else
		{
			// Double submission attempt.
		}

		this.lastSearchObj = searchObj;
		this.lastSearchTime = (new Date()).getTime();
	}
};

Comment.prototype.onCommentDelete = function(searchObj, data)
{
	// Reset our search object;
	this.completeQuery();

	// Note: the logic here is confusing, mutable and highly dependent on the
	// integrity and conventions in comment node contstruction being maintained.
	// changes in server side rendering will need to be reflected here.
	if(this.hasNest(searchObj.deletecomment) )
	{
		// Find this nodes child node container list item element.
		// Find Comment->Find parent li->immediate sibling (next) should be a "comment nest container" li.
		var nestedLINode = jQuery("#comment-number-"+searchObj.deletecomment).parent("div").next();

		// Dig through the nested list and get the children.
		var nestedChildren = nestedLINode.children(".comment-nested").children();

		jQuery("#comment-number-"+searchObj.deletecomment).parent("div").replaceWith(nestedChildren);
	}
	else
	{
		jQuery("#comment-number-"+searchObj.deletecomment).parent("div").empty();
	}
};

Comment.prototype.completeQuery = function()
{
	this.lastSearchObj = null;
	this.lastSearchTime = null;
};

Comment.prototype.hasNest = function(comment_id)
{
	parentComment = jQuery("#comment-number-"+comment_id).parent("div");
	hasNest = parentComment.next().children(".comment-nested").length > 0 ? true : false;
	return hasNest;
};

Comment.prototype.appendReply = function(parent_id, commentData)
{
	parentComment = jQuery("#comment-number-"+parent_id).parent("div");

	commentNode = jQuery(commentData);
	hasNest = 	parentComment.next().children(".comment-nested").length > 0 ? true : false;
	if(hasNest)
	{
		commentNode.wrap("<div></div>");
		// Select parent, commentNode still points to div, not li.
		parentComment.next().children(".comment-nested").prepend(commentNode.parent());
	}
	else
	{
		// Select parent, commentNode still points to div, not li.
		commentNode.wrap("<div class = 'comment-nest-container'><ul class = 'comment-nested'><div></div></div></div>");

		parentComment.after(commentNode.parent().parent().parent());
	}

	// Clear comment data
	jQuery("#comment-subject").val(" ");
	jQuery("#comment-body").val(" ");
};

Comment.prototype.appendMain = function(commentData)
{
	parentList = jQuery("#comment-tree-main");
	commentNode = jQuery(commentData);
	commentNode.wrap("<div></div>");
	parentList.prepend(commentNode.parent());

	// Clear comment data
	jQuery("#comment-subject").val(" ");
	jQuery("#comment-body").val(" ");

};

Comment.prototype.replyTo = function(post_id)
{
	if(this.showCaptcha) {
		jQuery("#recaptcha-container").show();
		Recaptcha.create(this.captchaPublicKey,
		"recaptcha-container", {
		   theme: "clean",
		   callback: Recaptcha.focus_response_field
		});
	}
	parentComment = jQuery("#comment-number-"+post_id);
	replyForm = jQuery("#comment-post-form");

	if(this.lastReply == post_id) {
		replyForm.hide();
		this.lastReply = null;
	} else {
		replyForm.show();
		this.lastReply = post_id;
	}
	replyForm.children("#comment-subject, #comment-body").val("");
	parentComment.after(replyForm);
	jQuery(replyForm).children("#comment-parent").val(post_id);

};

Comment.prototype.replyMain = function()
{
	if(this.showCaptcha)
	{
		jQuery("#recaptcha-container").show();
		Recaptcha.create(this.captchaPublicKey,
		"recaptcha-container", {
		   theme: "clean",
		   callback: Recaptcha.focus_response_field
		});
	}
	replyForm = jQuery("#comment-post-form");
	replyHeader = jQuery("#comment-header");

	if(this.lastReply != -1) {
		replyForm.show();
		this.lastReply = -1;
	}
	else
	{
		replyForm.hide();
		this.lastReply = null;
	}

	replyForm.insertAfter(jQuery(replyHeader));
	jQuery(replyForm).children("#comment-parent").val(-1);
};

Comment.prototype.onPostCommentClick = function()
{
	subject = jQuery("#comment-subject").val();
	body = jQuery("#comment-body").val();
	parentval = jQuery("#comment-parent").val();

	this.saveComment(subject,body,parentval);
};

Comment.prototype.onCommentSaved = function(searchObj, data)
{
	// Reset our search object;
	this.completeQuery();

	// Check for errors post submission (ie recaptcha failure).
	if(jQuery(data).hasClass("error")) {
		if(this.showCaptcha)
		{
			Recaptcha.reload();
			Recaptcha.focus_response_field();
		}
		this.displayError(data);
	}
	else {
		/* move our form out of the comment tree
		so that the replacement doesn't kill it */
		replyForm = jQuery("#comment-post-form");
		replyHeader = jQuery("#comment-header");
		replyHeader.after(replyForm);
		replyForm.hide();


		if(parseInt(searchObj.parent_comment) > 0)
		{
			this.appendReply(searchObj.parent_comment,data);
		}
		else
		{
			this.appendMain(data);
		}
	}
};

Comment.prototype.toggleDirection = function() {
	if(this.g_direction == 'asc') {
		jQuery("#comment-direction").addClass("comment-desc");
		jQuery("#comment-direction").removeClass("comment-asc");

		this.g_direction = 'desc';
	} else {
		jQuery("#comment-direction").removeClass("comment-desc");
		jQuery("#comment-direction").addClass("comment-asc");

		this.g_direction = 'asc';
	}

	this.orderBy(this.g_orderBy,this.g_direction);
};

Comment.prototype.toggleOrderBy = function(order, caller) {
	var orderObj = jQuery("#comment-order");
	orderObj.children("#comment-order-display").text(order);
	orderObj.children("#comment-order-display").text(jQuery(caller).text());
	this.g_orderBy = order;

	this.orderBy(this.g_orderBy,this.g_direction);
};

Comment.prototype.displayError = function(data)
{
	jQuery("#comment-error").show();
	jQuery("#comment-error").html(data);
};

Comment.prototype.clearError = function()
{
	jQuery("#comment-error").empty();
};

window.InPlace = function InPlace(field, location, params) {
	this.originalField = jQuery(field);
	this.wrapperField = null;
	this.clickOutside = null;
	this.params = params;
	this.location = location;

	switch(this.originalField.get(0).nodeName) {
		case 'H1':
		case 'H2':
		case 'STRONG':
		case 'H3':
			this.input(this.originalField);
			break;
		case 'P':
			this.textArea(this.originalField);
			break;
	};

};

InPlace.prototype.release = function(evt)
{
	jQuery('body').unbind('mousedown',this.clickOutside);

	if(this.wrapperField != null) {
		this.originalField.css('display','');
		this.wrapperField.css('display','none');
	}

};

InPlace.prototype.wrapper = function (field )
{
	var inPlaceObj = this;


	var wrapperEl = jQuery('<div id="'+field.get(0).id+'_inplace" class = "inplace '+this.params['nodeType']+'"></div>');
	var controlEl = jQuery('<div class="control"></div>');
	var cancelEl = jQuery('<div class = "cancel"><span>cancel</span></div>');
	var okEl = jQuery('<div class = "ok"><span>okay</span></div>');

	var width = 0;
	var height = 0;
	if(this.params['nodeType'] == 'input') {
		var inputEl = jQuery('<input class = "input" name="data" value=""></input>');
		width = field.innerWidth();
		height = field.innerHeight();
	}
	else if(this.params['nodeType'] == 'textarea'){
		var inputEl = jQuery('<textarea class = "textarea" name="data" value=""></textarea>');
		width = field.innerWidth();
		height = field.innerHeight();
		if(height < 30) {
			height = 60;
		}
	}

	wrapperEl.width(width);
	wrapperEl.height(height);

	inputEl.width(width);
	inputEl.height(height);

	inputEl.val(jQuery.trim(field.text()));

	cancelEl.mousedown(
		function(evt)
		{
			evt.stopPropagation();
			inPlaceObj.release(evt);
		}
	);

	inputEl.mousedown(
		function(evt) {
			evt.stopPropagation();
		}
	);

	if(this.params['nodeType'] == 'input') {

	}

	okEl.mousedown(
		function(evt) {
			evt.stopPropagation();
			inPlaceObj.params['inplace_data'] = inputEl.val();
			jQuery.post(
				inPlaceObj.location,
				inPlaceObj.params,
				function(data, textResponse) {
					inPlaceObj.update(data);
				}
			);
			return false;
		}
	);

	wrapperEl.mousedown(
		function (evt) {
			evt.stopPropagation();
			return false;
		}
	);

	this.clickOutside = function(evt)
	{
		evt.stopPropagation();
		inPlaceObj.release();
		return false;
	}

	jQuery('body').bind('mousedown',this.clickOutside);
	// Force dimensions on controlEl
	jQuery('body').append(controlEl);
	jQuery('body').append(wrapperEl);

	controlEl.append(cancelEl);
	controlEl.append(okEl);

	wrapperEl.append(inputEl);
	wrapperEl.append(controlEl);

	wrapperEl.css('position','absolute');

	dim = field.offset();
	wrapperEl.css('top',dim.top+'px');
	wrapperEl.css('left',dim.left+'px');

	jQuery('body').append(wrapperEl);

	controlEl.fadeIn(5,0.6);
	//new DropShadow(controlEl, 3, -2);

	return wrapperEl;
};

InPlace.prototype.textArea = function (field)
{
	jQuery.extend(this.params, {'nodeType':'textarea'});

	this.wrapperField = this.wrapper(field);

	this.originalField.css('display','');

};

InPlace.prototype.input = function(field)
{
	jQuery.extend(this.params, {'nodeType':'input'});

	this.wrapperField = this.wrapper(field);

	this.originalField.css('display','');

};

InPlace.prototype.update = function( data )
{
	this.originalField.html(data);
	this.release();
};

})(jQuery);