// requires jquery
if(!window.$){
	document.write("<script src='" + GLOBALS.contextPath + "/js/jquery-1.4.2.min.js'></script>");
}

function WorldWriteFeed(config){
	this.subjectId = config.subjectId || -1;
	this.pageNumber = config.pageNumber || 1;
	this.pageSize = config.pageSize || 7;
	this.containerId = config.containerId;
	this.numberToDisplay = config.numberToDisplay || 7;
	this.debug = config.debug || true;

	$(this.containerId).html(this.BASE_TEMPLATE);

	this.load();
}

WorldWriteFeed.prototype.url = GLOBALS.contextPath + "/ajax/loadWorldWritesFeed";

WorldWriteFeed.prototype.BASE_TEMPLATE = ["<div class='loading'>",
                                          "<img src='" + GLOBALS.contextPath + "/images/wait24.gif'/> loading world write feed",
                                          "</div>",
                                          "<div class='content'>",
                                          "<div class='worldWriteFeedLeftArrow arrow'>&lt;</div>",
                                          "<div class='worldWriteFeedContentContainer'>",
                                          "</div>",
                                          "<div class='worldWriteFeedRightArrow arrow'>&gt;</div>",
                                          "</div>",
                                          "<br style='clear: both;'/>"].join("");

WorldWriteFeed.prototype.WRITE_BACKGROUND = ["<div>",
                                             "<img src='{replace-background}' class='worldWriteFeedBackground' onerror='this.src=\"" + GLOBALS.contextPath + "/images/little_biggy.jpg\"' />",
                                             "<div class='worldWriteFeedContent'>",
                                             "{replace-content}",
                                             "</div>",
                                             "</div>"].join("");

WorldWriteFeed.prototype.REVIEW_TEMPLATE = ["<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-writerId}'><span class='peopleLink worldWriteFeedSubject'>{replace-writerName}</span></a>",
                                            " reviews <br/>",
                                            "<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-subjectId}'><span class='peopleLink worldWriteFeedSubject'>{replace-subjectName}</span></a>",
                                            " <span class='roleFont worldWriteFeedRole'>{replace-roleName}</span>"].join("");

WorldWriteFeed.prototype.RATING_TEMPLATE = ["<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-writerId}'><span class='peopleLink worldWriteFeedSubject'>{replace-writerName}</span></a>",
                                            " rates<br/>",
                                            "<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-subjectId}'><span class='peopleLink worldWriteFeedSubject'>{replace-subjectName}</span></a>",
                                            " <span class='roleFont worldWriteFeedRole'>{replace-roleName}</span>",
                                            " <span class='worldWriteFeedValue'>{replace-value}</span> ",
                                            " for <span class='worldWriteFeedCriterion'>{replace-criterionName}</span>"].join("");

WorldWriteFeed.prototype.RATING_REVIEW_TEMPLATE = ["<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-writerId}'><span class='peopleLink worldWriteFeedSubject'>{replace-writerName}</span></a>",
		                                           " rates<br/>",
		                                           "<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-subjectId}'><span class='peopleLink worldWriteFeedSubject'>{replace-subjectName}</span></a>",
		                                           " <span class='roleFont worldWriteFeedRole'>{replace-roleName}</span>",
		                                           " <span class='worldWriteFeedValue'>{replace-value}</span> ",
		                                           "for review of ",
		                                           "<a href='{replace-reviewedId}'><span class='peopleLink worldWriteFeedSubject'>{replace-reviewedName}</span></a>"].join("");

WorldWriteFeed.prototype.PICK_TEMPLATE = ["<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-writerId}'><span class='peopleLink worldWriteFeedSubject'>{replace-writerName}</span></a>",
                                          " picks<br/>",
                                          "<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-subjectId}'><span class='peopleLink worldWriteFeedSubject'>{replace-subjectName}</span></a>",
                                          " <span class='roleFont worldWriteFeedRole'>{replace-roleName}</span>"].join("");

WorldWriteFeed.prototype.REJECT_TEMPLATE = ["<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-writerId}'><span class='peopleLink worldWriteFeedSubject'>{replace-writerName}</span></a>",
                                            " rejects<br/>",
                                            "<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-subjectId}'><span class='peopleLink worldWriteFeedSubject'>{replace-subjectName}</span></a>",
                                            " <span class='roleFont worldWriteFeedRole'>{replace-roleName}</span>"].join("");

WorldWriteFeed.prototype.COMMENTS_TEMPLATE = ["<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-writerId}'><span class='peopleLink worldWriteFeedSubject'>{replace-writerName}</span></a>",
                                              " comments on<br/>",
                                              "<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-subjectId}'><span class='peopleLink worldWriteFeedSubject'>{replace-subjectName}</span></a>",
                                              " <span class='roleFont worldWriteFeedRole'>{replace-roleName}</span> ",
                                              "\"<span class='worldWriteFeedComment'>{replace-comment}</span>\""].join("");

WorldWriteFeed.prototype.BLURBS_TEMPLATE = ["<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-writerId}'><span class='peopleLink worldWriteFeedSubject'>{replace-writerName}</span></a>",
                                            " blurbs on<br/>",
                                            "<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-subjectId}'><span class='peopleLink worldWriteFeedSubject'>{replace-subjectName}</span></a>",
                                            " <span class='roleFont worldWriteFeedRole'>{replace-roleName}</span> ",
                                            "\"<span class='worldWriteFeedBlurb'>{replace-blurb}</span>\""].join("");

WorldWriteFeed.prototype.ADD_SUBJECT_TEMPLATE = ["<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-writerId}'><span class='peopleLink worldWriteFeedSubject'>{replace-writerName}</span></a>",
                                                 " adds<br/>",
                                                 "<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-subjectId}'><span class='peopleLink worldWriteFeedSubject'>{replace-subjectName}</span></a>",
                                                 " <span class='roleFont worldWriteFeedRole'>{replace-roleName}</span>"].join("");

WorldWriteFeed.prototype.EDIT_SUBJECT_TEMPLATE = ["<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-writerId}'><span class='peopleLink worldWriteFeedSubject'>{replace-writerName}</span></a>",
                                                  " edits<br/>",
                                                  "<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-subjectId}'><span class='peopleLink worldWriteFeedSubject'>{replace-subjectName}</span></a>",
                                                  " <span class='roleFont worldWriteFeedRole'>{replace-roleName}</span>"].join("");

WorldWriteFeed.prototype.ANSWERED_PUBLIC_QUESTION_TEMPLATE = ["<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-writerId}'><span class='peopleLink worldWriteFeedSubject'>{replace-writerName}</span></a>",
                                            " answered the question '{replace-question}' on ",
                                            "<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-subjectId}'><span class='peopleLink worldWriteFeedSubject'>{replace-subjectName}</span></a>"].join("");

WorldWriteFeed.prototype.ANSWERED_PRIVATE_QUESTION_TEMPLATE = ["<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-writerId}'><span class='peopleLink worldWriteFeedSubject'>{replace-writerName}</span></a>",
                                            " answered a private question on ",
                                            "<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-subjectId}'><span class='peopleLink worldWriteFeedSubject'>{replace-subjectName}</span></a>"].join("");

WorldWriteFeed.prototype.ASKED_PRIVATE_QUESTION_TEMPLATE = ["<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-writerId}'><span class='peopleLink worldWriteFeedSubject'>{replace-writerName}</span></a>",
                                            " asked a private question on ",
                                            "<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-subjectId}'><span class='peopleLink worldWriteFeedSubject'>{replace-subjectName}</span></a>"].join("");

WorldWriteFeed.prototype.ASKED_PUBLIC_QUESTION_TEMPLATE = ["<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-writerId}'><span class='peopleLink worldWriteFeedSubject'>{replace-writerName}</span></a>",
                                            " asked the question '{replace-question}' on ",
                                            "<a href='" + GLOBALS.contextPath + "/viewSubject/{replace-subjectId}'><span class='peopleLink worldWriteFeedSubject'>{replace-subjectName}</span></a>"].join("");

WorldWriteFeed.prototype.load = function(){
	$(this.containerId + " .loading").show();

	var scope = this;
	scope.loading = true;

	$.ajax({
		url: this.url,
		data: {
			subjectId: this.subjectId,
			pageNumber: this.pageNumber,
			pageSize: this.pageSize,
			formatted: this.debug
		},
		success: function(response){
			scope.loaded(response);
			scope.render();
		}
	});
}

WorldWriteFeed.prototype.loaded = function(response){
	this.response = new Function('return ' + response)();

	if(!this.data){
		this.data = new Array(this.response.totalSetSize);
	}

	this.currentPageStart = ((this.pageNumber -1) * this.pageSize) + 1;
	this.currentPageEnd = this.pageNumber * this.pageSize;

	if(this.currentPageEnd > this.response.totalSetSize){
		this.currentPageEnd = this.response.totalSetSize;
	}

	this.data.splice.apply(this.data, [this.currentPageStart - 1, this.response.writeEvents.length].concat(this.response.writeEvents));

	this.start = this.start || this.currentPageStart -1;
	this.end = this.end || (this.currentPageStart -1) + this.numberToDisplay;

	if(this.end > this.data.length){
		this.end = this.data.length;
	}

	this.loading = false;
}

// to the left
WorldWriteFeed.prototype.next = function(e){
	var scope = e.data;

	if(scope.end >= scope.response.totalSetSize || scope.loading){
		return;
	}

	scope.start++;
	scope.end++;

	scope.moveNext = true;

	if(!scope.data[scope.end]){
		scope.pageNumber++;
		scope.load();
	} else {
		scope.render();
	}
}

// to the right
WorldWriteFeed.prototype.prev = function(e){
	var scope = e.data;

	if(scope.start == 0 || scope.loading){
		return;
	}

	scope.start--;
	scope.end--;

	scope.moveNext = false;

	if(!scope.data[scope.start]){
		scope.pageNumber--;
		scope.load();
	} else {
		scope.render();
	}
}

WorldWriteFeed.prototype.render = function(){
	var container = $(this.containerId),
	    contentDiv = container.find(".worldWriteFeedContentContainer"),
	    rightArrow = container.find(".worldWriteFeedRightArrow"),
	    leftArrow = container.find(".worldWriteFeedLeftArrow");

	// don't show the arrows if there are no more writes in that direction.
	rightArrow[this.start == 0 ? "hide" : "show"]();
	leftArrow[this.end == this.data.length-1 ? "hide" : "show"]();

	if(!this.rendered){
		this.rendered = true;

		var html = [];

		for(var i=this.end-1; i >= this.start; i--){
			var writeEvent = this.data[i];
			html.push(this.renderCellMarkup(writeEvent));
		}
		contentDiv.html(html.join(""));
		leftArrow.bind("click", this, this.next);
		rightArrow.bind("click", this, this.prev);
		container.find(".content ").show();
	}
	else {
		if(this.moveNext){
			var last,
				newDiv;

			contentDiv.prepend(this.renderCellMarkup(this.data[this.end]));
			var newDiv = contentDiv.children("div:first");
			newDiv.hide();
			last = contentDiv.children("div:last");
			last.remove();
			newDiv.show(1000);
		}
		else {
			var first,
				next,
				newDiv,
				movePrevRoutine,
				writeEvent,
				scope = this;

			writeEvent = this.data[this.start];

			movePrevRoutine = function(){
				contentDiv.append(scope.renderCellMarkup(writeEvent));
				newDiv = contentDiv.children("div:last");
				newDiv.hide();

				first = contentDiv.children("div:first");
				next = first.next();

				if(scope.movePrevQueue.length == 1){
					newDiv.show(1000);
					first.animate({
						width: 0,
						marginLeft: 0
					},
					1000,
					function(){
						$(this).remove();
						scope.movePrevQueue.shift(); // we are now done so dequeue the first
					});
				} else {
					newDiv.show();
					first.remove();
					scope.movePrevQueue.shift(); // we are now done so dequeue the first
				}
			};

			// enqueue the move previous render request
			this.movePrevQueue = this.movePrevQueue || [];
			this.movePrevRoutineLockId = this.movePrevRoutineLockId || 0;
			this.movePrevQueue.push({
					lockId : ++this.movePrevRoutineLockId,
					fn: movePrevRoutine
				});

			// This block of code is in charge of ensuring that
			// each movePrevRoutine executes in order by holding
			// a virtual lock on the queue until the execution
			// has completed and the lock is released.
			if(this.movePrevQueue[0].lockId == this.movePrevRoutineLockId){
				this.movePrevQueue[0].fn(); // first in line so just execute
			} else {
				// wait for the current routine's lock to release
				// check again in 200 milliseconds
				var movePrevRoutineInstanceLockId = this.movePrevRoutineLockId;
				setTimeout(function(){
					if(scope.movePrevQueue[0].lockId == movePrevRoutineInstanceLockId){
						// the lock is released execute the next in line
						scope.movePrevQueue[0].fn();
					} else {
						// still holds the lock try again in 200 milliseconds
						setTimeout(arguments.callee, 200);
					}
				}, 200);
			}
		}
	}
	container.find(".loading").hide();
}


WorldWriteFeed.prototype.renderCellMarkup = function(writeEvent){
	var markup = "";
	switch(writeEvent.type){
		case "RATING": markup = this.RATING_TEMPLATE.replace("{replace-writerId}", writeEvent.writerId)
													.replace("{replace-writerName}", writeEvent.writerName)
													.replace("{replace-subjectId}", writeEvent.subjectId)
													.replace("{replace-subjectName}", writeEvent.subjectName)
													.replace("{replace-roleName}", writeEvent.roleName || "")
													.replace("{replace-value}", Math.round(writeEvent.value * 100) / 100)
													.replace("{replace-criterionName}", writeEvent.contextName);
			break;
		case 'RATING_REVIEW': markup = this.RATING_REVIEW_TEMPLATE.replace("{replace-writerId}", writeEvent.writerId)
																  .replace("{replace-writerName}", writeEvent.writerName)
																  .replace("{replace-subjectId}", writeEvent.subjectId)
																  .replace("{replace-subjectName}", writeEvent.subjectName)
															      .replace("{replace-roleName}", writeEvent.roleName || "")
															      .replace("{replace-value}", Math.round(writeEvent.value * 100) / 100)
															      .replace("{replace-reviewedId}", writeEvent.contextId)
															      .replace("{replace-reviewedName}", writeEvent.contextName);
			break;
		case 'REVIEW': markup = this.REVIEW_TEMPLATE.replace("{replace-writerId}", writeEvent.writerId)
													.replace("{replace-writerName}", writeEvent.writerName)
													.replace("{replace-subjectId}", writeEvent.subjectId)
													.replace("{replace-subjectName}", writeEvent.subjectName)
													.replace("{replace-roleName}", writeEvent.roleName || "");
			break;
		case "PICK": markup = this.PICK_TEMPLATE.replace("{replace-writerId}", writeEvent.writerId)
												.replace("{replace-writerName}", writeEvent.writerName)
				  							  	.replace("{replace-subjectId}", writeEvent.subjectId)
				  							  	.replace("{replace-subjectName}", writeEvent.subjectName)
				  							  	.replace("{replace-roleName}", writeEvent.roleName || "");
			break;
		case 'REJECT': markup = this.REJECT_TEMPLATE.replace("{replace-writerId}", writeEvent.writerId)
													.replace("{replace-writerName}", writeEvent.writerName)
													.replace("{replace-subjectId}", writeEvent.subjectId)
													.replace("{replace-subjectName}", writeEvent.subjectName)
													.replace("{replace-roleName}", writeEvent.roleName || "");
			break;
		case 'COMMENT': var commentContent = writeEvent.value || "";
					    if(commentContent.length > 50){
					    	commentContent = commentContent.substring(0, 50) + "...";
					    }
					    markup = this.COMMENTS_TEMPLATE.replace("{replace-writerId}", writeEvent.writerId)
					    							   .replace("{replace-writerName}", writeEvent.writerName)
							  						   .replace("{replace-subjectId}", writeEvent.subjectId)
							  						   .replace("{replace-subjectName}", writeEvent.subjectName)
							  						   .replace("{replace-roleName}", writeEvent.roleName || "")
							  						   .replace("{replace-comment}", commentContent);
			break;
		case 'BLURB':  var blurbContent = writeEvent.value || "";
					   if(blurbContent.length > 50){
						   blurbContent = blurbContent.substring(0, 50) + "...";
					   }
					   markup = this.BLURBS_TEMPLATE.replace("{replace-writerId}", writeEvent.writerId)
				  									.replace("{replace-writerName}", writeEvent.writerName)
												    .replace("{replace-subjectId}", writeEvent.subjectId)
												    .replace("{replace-subjectName}", writeEvent.subjectName)
												    .replace("{replace-roleName}", writeEvent.roleName || "")
												    .replace("{replace-blurb}", blurbContent);
			break;
		case "ADD_SUBJECT": markup = this.ADD_SUBJECT_TEMPLATE.replace("{replace-writerId}", writeEvent.writerId)
															  .replace("{replace-writerName}", writeEvent.writerName)
															  .replace("{replace-subjectId}", writeEvent.subjectId)
															  .replace("{replace-subjectName}", writeEvent.subjectName)
															  .replace("{replace-roleName}", writeEvent.roleName || "");
			break;
		case "EDIT_SUBJECT": markup = this.EDIT_SUBJECT_TEMPLATE.replace("{replace-writerId}", writeEvent.writerId)
																.replace("{replace-writerName}", writeEvent.writerName)
																.replace("{replace-subjectId}", writeEvent.subjectId)
																.replace("{replace-subjectName}", writeEvent.subjectName)
																.replace("{replace-roleName}", writeEvent.roleName || "");
			break;
        case "ANSWERED_PUBLIC_QUESTION":
            markup = this.ANSWERED_PUBLIC_QUESTION_TEMPLATE.replace("{replace-writerId}", writeEvent.writerId)
                                                           .replace("{replace-writerName}", writeEvent.writerName)
                                                           .replace("{replace-subjectId}", writeEvent.subjectId)
                                                           .replace("{replace-subjectName}", writeEvent.subjectName)
                                                           .replace("{replace-question}", writeEvent.value);
            break;
        case 'ANSWERED_PRIVATE_QUESTION' :
            markup = this.ANSWERED_PRIVATE_QUESTION_TEMPLATE.replace("{replace-writerId}", writeEvent.writerId)
                                                            .replace("{replace-writerName}", writeEvent.writerName)
                                                            .replace("{replace-subjectId}", writeEvent.subjectId)
                                                            .replace("{replace-subjectName}", writeEvent.subjectName);
            break;
        case 'ASKED_PUBLIC_QUESTION' :
            markup = this.ASKED_PUBLIC_QUESTION_TEMPLATE.replace("{replace-writerId}", writeEvent.writerId)
                                                        .replace("{replace-writerName}", writeEvent.writerName)
                                                        .replace("{replace-subjectId}", writeEvent.subjectId)
                                                        .replace("{replace-subjectName}", writeEvent.subjectName)
                                                        .replace("{replace-question}", writeEvent.value);
            break;
        case 'ASKED_PRIVATE_QUESTION' :
            markup = this.ASKED_PRIVATE_QUESTION_TEMPLATE.replace("{replace-writerId}", writeEvent.writerId)
                                                         .replace("{replace-writerName}", writeEvent.writerName)
                                                         .replace("{replace-subjectId}", writeEvent.subjectId)
                                                         .replace("{replace-subjectName}", writeEvent.subjectName);
            break;
	}

	return this.WRITE_BACKGROUND.replace("{replace-background}", writeEvent.subjectImageURL || (GLOBALS.contextPath + "/images/little_biggy.jpg"))
								.replace("{replace-content}", markup);
}
