////////////////////////////////////////
// Thread Class representing a thread //
////////////////////////////////////////

function Thread(title) {
	this.comments = new Array();
	this.title = title;
}

//add a comment to the thread
Thread.prototype.addComment = function(comment) {
	this.comments[comment.getId()] = comment;
}

//remove a comment from the thread
Thread.prototype.removeComment = function(comment) {
	this.comments[comment.getId()] = "";
}

Thread.prototype.getCommentById = function(id) {
	return this.comments[id];
}

// set the title for the thread
Thread.prototype.setTitle = function(title) {
	this.title = title;
}

// get the title for the thread
Thread.prototype.getTitle = function() {
	return this.title;
}



//=====================================================================
// Thread Helper Functions
//=====================================================================



function countLines(obj) {
	cols = obj.cols;
	strtocount = obj.value;
    var hard_lines = 1;
    var last = 0;
    while ( true ) {
        last = strtocount.indexOf("\n", last+1);
        hard_lines ++;
        if ( last == -1 ) break;
    }
    var soft_lines = Math.round(strtocount.length / (cols-1));
    var hard = eval("hard_lines  " + unescape("%3e") + "soft_lines;");
    if ( hard ) soft_lines = hard_lines;
    obj.rows = soft_lines;
}


	function UNhideObj(elementName)
	{
		nav = $(elementName).style;
		nav.display='block';
	}

	function HideObj(elementName)
	{
		nav = $(elementName).style;
		nav.display='none';
	}

	function moveToReply(id, thread) {
		setReplyTags(id,thread);
		$('parentId').value=id;		
		
		document.documentElement.scrollTop = ($('replyResult').cumulativeOffset().top);
		$('replyBody').focus();
	}
	
	
	function setReplyTags(id,thread) {
		newTagsArray = thread.getCommentById(id).getTags().clone(); //Set the array of inherited tags to the ones from the parent comment
		newGeotagsArray = thread.getCommentById(id).getGeotags().clone();
		copyTags(thread, "reply", id);
	}
	
	
	// Replicates tags from one comment to another
	// toId = comment to add them to. ex: 'reply'
	// fromId = comment to use them from. ex: 1234
	function copyTags(thread, toId, fromId) {

		var tArray = thread.getCommentById(fromId).getTags();
		var toComment = thread.getCommentById(toId);
		
		for(i in tArray) {
			if(tArray.hasOwnProperty(i)) {
				toComment.addTag(tArray[i].clone());
			}
		}

		var gtArray = thread.getCommentById(fromId).getGeotags();
		for(i in gtArray) {
			if(gtArray.hasOwnProperty(i)) {
				toComment.addGeotag(gtArray[i].clone());
			}
		}		
		
	}

//////////////////////////////
// Thread Edit Functions    //
//////////////////////////////
						

function setEditText(value,id){
	$('editBody_'+id).innerHTML = value;		
}

function updateBody(request,id,thread) {

	var editResults = request.responseText.evalJSON(true);

	var newTextAreaBody = $('editBody_'+id).value;

	newTextAreaBodyNoHTML = stripHTML(newTextAreaBody);

	newTextAreaBody = addURLLinks(newTextAreaBodyNoHTML);
	thread.getCommentById(id).setBody(newTextAreaBody);
	
	$('commentBody_'+id).innerHTML = newTextAreaBody.replace(/\r\n|\r|\n/g,'<br/>');

    $('editLink_'+id).style.display='inline';
    $('replyLink_'+id).style.display='inline';
	$('commentBody_'+id).style.display='block';
	$('editBox_'+id).style.display='none';
	setEditText(newTextAreaBodyNoHTML,id);
}
			
	function updateEditTime (id)
	{
		timeLeft = parseInt($('editTimeValue_'+id).innerHTML)-1000;
		$('editTimeValue_'+id).innerHTML = timeLeft;
		if(timeLeft > 1) {
			minutes = Math.floor(timeLeft/60000);
			seconds = (timeLeft/1000)%60;
			var timeString = "(";
			if(minutes >= 2) {
				timeString += minutes + " minutes left to edit";
			}else if(minutes >= 1) {
				timeString += minutes + " minute left to edit"
			}
			if(minutes < 1) {
				timeString += seconds + " seconds left to edit";
			}
			timeString += ")";
			
			$('editTime_'+id).innerHTML = timeString;
		} else {
			$('editTime_'+id).innerHTML = "(Your time is up!)";
			$('editLink_'+id).style.display = "none";
			$('editBox_'+id).style.display = "none";
			editActions = $$(".edit_action_"+id);
			for(i = 0; i < editActions.length; i++) {
				editActions[i].style.display = "none";
			}
			$('commentBody_'+id).style.display='block';			
		}
	}						
						
	function disableButton(id) {
		$(id).disabled = true;
	}
	
	function enableButton(id) {
		$(id).disabled = false;
	}


	// e = event
	// id = postId number
	// mode = create or edit
	function checkForAdd(e, id, mode,thread) {

		if((e.keyCode == 188) || ((e.keyCode == 13) && ($$('li.selected').length < 1))){
			if(mode == "create") {
				addTagToArray($('create_tags').value,mode,mode,newTagsArray,thread); 
				setTimeout("clearInput('create_tags')",10);	
				setTimeout("focusInput('create_tags')",10);
			} else if(mode == "edit") {
				addTagPost(id,thread);
			} else {
				addTagToArray($('newTags_'+id).value,id,mode,newTagsArray,thread);
				setTimeout("clearInput('newTags_"+id+"')",10); 
				setTimeout("focusInput('newTags_"+id+"')",10);
			}
		}
	}
	
	//Adds tag on client side and posts to the server
	function addTagPost(id,thread) {
		new Ajax.Request('/post/addTag', {method: 'post', 
										  postBody: 'commentId='+id+'&commit=&newTags_'+id+'='+$('newTags_'+id).value, 
										  asynchronous:true, 
										  evalScripts:false, onComplete:function(request, json){ 
																			addTagToArray(request.responseText,id,'edit',newTagsArray,thread); 
																			$('commentTags_'+id).value += request.responseText + ', ';
																			clearInput('newTags_'+id);
																			focusInput('newTags_'+id);
																		}
										}
						);
	}
	
	// mode defines whether we are in create mode or adding more tags mode
	function addTagToArray(value, id, mode, tArray,thread) {

		if(mode == 'create') {
			//hides the error message to add tags as soon as they click the Add Tags link
			$('create_tags_error2').style.display = "none";
		}

		valueOrig = value;
		// Trim whitespace
		value = trim(value);
		if((value != "") && (valueOrig != 'e.g. "baseball" or "Baltimore" or "brian"')){

				if(mode == 'create') {			
					geotagCheck(value);
					previousTagValue = value;
					previousTagConfirmed = false;
					
				}

				if(!thread.getCommentById(id).getTagByKeyword(value)) {
					thread.getCommentById(id).addTag(new Tag(value));
					createNewTagBlocks(id, new Tag(value), "tag", mode, tArray,thread,true);
				} else {
					var tagForId = value.replace(/^\s+|\s+|[\']+|[\"]+/g, '');
					Effect.Shake('tag_'+id+'_'+tagForId, {duration: 0.2, distance: 2});
					new Effect.Highlight('tag_'+id+'_'+tagForId);					
				}

		} 
	}
	
	// Mode = create or edit.  This determines whether the delete function should send a request to the server or not
	function createNewTagBlocks(id, tag, tagType, mode, tArray, thread, removeable) {

		if(tagType) {
			tagType = tagType;
		} else {
			tagType = "tag";
		}

		var tagText = tag.getKeyword();
		//Strip white space
		tagText = tagText.replace(/^\s+|\s+$/g, '');

		var tagForId = tagText.replace(/^\s+|\s+|[\']+|[\"]+/g, '');
		// Make sure to remove all white spaces so id works for multi word tags
		// Create means is this post being created at the time.  If it is, we dont need to do an ajax call to remove the tag from the database as well.  Only need to remove the tag block and from the data to be passed
		if((mode == "create") || (mode == "reply")){	
			
			tArray[tagText] = tag;
			
			var tagTextBlock = new Element('span', {'class': tagType+"_text"}).update(tagText);
			tagTextBlock.insert(new Element('img', { 'src': "/images/icons/cross.gif", 'class': "edit_action_"+id, 'style': "cursor: pointer;", 'name': "commit", 'alt': "Delete", 'height': 10, 'width': 10 }).observe('click', function(event){ removeTagBlock(id,tag,tagType,tArray,thread)}));
			
			var tagBlock = new Element('a', { 'class': tagType+" tag tagblock_"+tagType, 'id': "tag_"+id+"_"+tagForId }).insert(tagTextBlock);


		
		}else {
		
			var tagBlock = new Element('a', { 'class': tagType+" tag tagblock_"+tagType, 'id': "tag_"+id+"_"+tagForId });			
			var tagTextBlock = new Element('span', {'class': tagType+"_text"}).update(tagText);
			
			if(removeable) {
				tagTextBlock.insert(new Element('img', { 'src': "/images/icons/cross.gif", 'class': "edit_action_"+id, 'style': "cursor: pointer;", 'name': "commit", 'alt': "Delete", 'height': 10, 'width': 10 }).observe('click', function(event){ removeTagBlock(id,tag,tagType,tArray,thread)}));
				tagBlock.insert(tagTextBlock);
			} else {
				tagBlock.update(tagTextBlock);
			}
		}
		$('tagList_'+id).insert(tagBlock);
		
	}
	
	
	// Returns the number of geotags and regular tags being created in a reply
	function getTotalTagsById(id,thread) {

		var tArray = theThread.getCommentById(id).getTags();
		var gtArray = theThread.getCommentById(id).getGeotags();
		
		var size=0;
		for(var i in tArray) {
			if (tArray.hasOwnProperty(i)) size++;	
		}
	
		for(var j in gtArray) {
			if (gtArray.hasOwnProperty(j)) size++;
		}				

		return size-1;
	}
	
	function removeTag(id, theTag, tagType, tArray, thread) {
		var numTags = getTotalTagsById(id,thread);
		if(numTags > 0) {						
			if(tagType === "tag") {

				new Ajax.Request('/post/deleteTag', {asynchronous:true, evalScripts:false, onComplete: function(request, json){removeTagBlock(id,theTag,tagType,tArray,thread);return false; }, parameters: {'commentId': id, 'tag': theTag.getKeyword()}});
			} else if(tagType === "geotag") {

				new Ajax.Request('/post/deleteGeotag', {asynchronous:true, evalScripts:false, onComplete: function(request, json){removeTagBlock(id,theTag,tagType,tArray,thread);return false; }, parameters: {'commentId': id, 'keyword': theTag.getKeyword(), 'longitude': theTag.getLongitude(), 'latitude': theTag.getLatitude()}});				
			}
	  	} else {
			showTagsError(id);
			setTimeout('hideTagsError("'+id+'")',5000);
		}			
	}

	function showTagsError(id) {
		Effect.Appear('tags_error_'+id);
	}

	function hideTagsError(id) {
		Effect.Fade('tags_error_'+id);
	}

	
	function removeTagBlock(id, tag, tagType, tArray, thread) {
		
		var numTags = getTotalTagsById(id,thread);
		if(numTags > 0) {	
			if(tagType == "geotag") {
				thread.getCommentById(id).removeGeotag(tag);
			} else {
				thread.getCommentById(id).removeTag(tag);
			}

			// id has no white space from multi word tags so need to strip white spaces and ' and "
			tagText = tag.getKeyword().replace(/^\s+|\s+|\"|\'/g, '');
		  	var d = $('tagList_'+id);
		  	var olddiv = $('tag_'+id+'_'+tagText);
		  	d.removeChild(olddiv);
	  	} else {
			showTagsError(id);
			setTimeout('hideTagsError("'+id+'")',5000);
		}
	}
	
	function clearInput(id) {
		obj = $(id);
		obj.value = "";
	}
	
	function focusInput(id) {
		obj = $(id);
		obj.focus();
	}


	//item is the contents of the LI element from the autocomplete
	//tagBlockInstance refers to the id used for showing the tag blocks.  ex:  create, reply
	function checkTagType(item, tagBlockInstance,thread) {
		itemClass = item.className;

		if(itemClass.indexOf('geotag') != -1) {
			// Since we are showing all geotag data with commas, we need to ensure we only pass the keyword for visually creating the tag block
			// Split up the data into an array.  We know we must have the first 3 elements
			// 0 longitude
			// 1 latitude
			// 2 keyword

			//Make sure the correct geotag element gets selected by choosing the .selected class from autocomplete list
			geotagSpans = $$("li.selected span");
			var longitude = geotagSpans[0].innerHTML;
			var latitude = geotagSpans[1].innerHTML;

			geotagElements = geotagSpans[2].innerHTML.split(',');		
			updateCurrentGeotag(longitude, latitude, geotagElements[0], geotagElements[1], geotagElements[2], geotagElements[3], geotagElements[4], geotagElements[5]);


			geoTagsArray[geoTagsArray.length] = currentGeoTag.clone();

			$('postGeotagArray').value = Object.toJSON(geoTagsArray);		

			createNewTagBlocks(tagBlockInstance, new Geotag(geotagElements[0], longitude, latitude), "geotag", "create",newTagsArray,thread,true);
			thread.getCommentById(tagBlockInstance).addGeotag(new Geotag(geotagElements[0], longitude, latitude));			

		} else if(itemClass.indexOf('user') != -1) {
			createNewTagBlocks(tagBlockInstance, new Tag(item.innerHTML), "user","create",newTagsArray,thread,true);
			thread.getCommentById(tagBlockInstance).addTag(new Tag(item.innerHTML));			
			$('tags').value = $('tags').value + "," + item.innerHTML;
		} else {
			addTagToArray(item.innerHTML,"create","create",newTagsArray,thread); 
			$('tags').value = $('tags').value + "," + item.innerHTML; 
		}
	}


	//This sets the tags to be posted from the array that we are using to keep track of them with
	function setTagsFromArray(tagsElementName, tArray) {

		var tmp = "";

		for (var i in tArray) {
			if((tArray.hasOwnProperty(i) && (tArray[i] != ""))) {
					tmp = tmp + ", " + tArray[i].getKeyword();
			}
		}	
		$(tagsElementName).value = tmp;
	}

	//This sets the geotags to be posted from the array that we are using to keep track of them with
	function setGeotagsFromArray(tagsElementName, tArray) {

		var tmp = "[";
		var count = 0;
		for (var i in tArray) {
			if((tArray.hasOwnProperty(i)) && (tArray[i] != "")) {
				if(count === 0) {
					tmp = tmp + Object.toJSON(tArray[i]);
				} else {
					tmp = tmp + ", " + Object.toJSON(tArray[i]);
				}
				count++;
			}
		}
		
		$(tagsElementName).value = tmp + "]";
	}
	
	
	
	//sets tag values in the array to empty value.  Removes tagBlocks for each of those tags
	function removeTagsFromArray(id, theArray) {

		for (var i in theArray) {
			if((theArray[i] != "") && (theArray.hasOwnProperty(i))) {			
				delete theArray[i];			
			}
		}		
		
	}


function geotagCheck(value) {
	geotagCheckMessageObj = $('geotagCheckMessage_tag')
	if(geotagCheckMessageObj) {
		Effect.Appear($('geotagCheckMessage'), {duration: 0.5});
		geotagCheckMessageObj.innerHTML = value;
	}
}


function completeReply(request, replyBody, newTags, geotags, username, thread) {
	createNewComment(request, replyBody, newTags, geotags, username, thread);
	document.replyForm.reset();
	enableButton('discussion_reply_button');
}

function beforeReply(thread) {
	setTagsFromArray('commentTags',thread.getCommentById("reply").getTags());
	setGeotagsFromArray('postGeotagArray',thread.getCommentById("reply").getGeotags());
}
