
/**
 * Constructor for the MessageController.
 * @param bounds
 */
com.foreclosure.MessagesController = function(bounds) {
	// the last address that has been fetched
	this.lastAddress = null;
	// the last bounds that have been fetched
	this.lastBounds = null;
	// radius to search
	this.radius = 0;
	// the list of current conversations
	this.conversations = null;
	
	
	// delegate for certain fetch operations, defaults to itself
	this.delegate = this;
	
	var that = this;
	// first message to display
	this.pagination = {
			indexStart: 0, // the start of the current page
			pageSize: RENDER.conversationsInPage,
			totalConversations:0, //total number of actual conversations
			reset : function() {
				this.indexStart=0;
				this.totalConversations=0;
			},
			linkEvents: function () {
				// wire the prev/next buttons if they are present
				var paginationPrev = dojo.query(".paginationPrev");
				if ( paginationPrev ) {
					paginationPrev.onclick(function(evt){that.prevPage();});
					dojo.query(".paginationNext").onclick(function(evt){that.nextPage();});
				}
			},
			display: function() {
				var paginationUi = dojo.byId("messagesPagination");
				var pages = 0;
				if ( this.totalConversations && this.totalConversations > 0 ) {
					pages = Math.ceil(this.totalConversations/this.pageSize);
				}
				if (  pages < 2 ) {
					paginationUi.style.display='none';
					return;
				} else {
					paginationUi.style.display='block';
				}
				var spans = dojo.query("span",paginationUi);
				if ( spans && spans.length==2 ) {
					spans[0].innerHTML = Math.floor(this.indexStart/this.pageSize)+1;
					spans[1].innerHTML = pages;
				}
				if  ( this.indexStart > 0 ) {
					dojo.query(".paginationPrev",paginationUi ).style("display","inline");
				} else {
					dojo.query(".paginationPrev", paginationUi ).style("display","none");
				}
				if ( this.totalConversations && (this.indexStart+this.pageSize<this.totalConversations) ) {
					dojo.query(".paginationNext",paginationUi ).style("display","inline");
				} else {
					dojo.query(".paginationNext",paginationUi ).style("display","none");
				}
			}
			

	};
	
	// the id for the conversation that has the focus
	this.lastRepliedToConversationId=null;
	
	// is the tab visible?
	this.visible = false;
	
	// the time on the server when the last list of messages is received
	this.serverTime=null;
	
	// output the UI for admin user? otherwise the submit will just fail on the server
	this.adminUser=false;
	
	this.categoryId=1;
	
	// if the current category requires moderation, this is needed to properly update the UI
	// note that the messages sent from the server automatically take this into account
	this.requireModeration = true;
};

com.foreclosure.MessagesController.prototype.onAddressChanged = function(arg) {
	if ( this.visible ) {
		this.pagination.reset();
		this.updateMessages();
	}
};

com.foreclosure.MessagesController.prototype.prevPage = function() {
	if ( this.pagination.indexStart >= this.pagination.pageSize ) {
		this.pagination.indexStart -= this.pagination.pageSize;
		this.doUpdateMessages();	
	}
};

com.foreclosure.MessagesController.prototype.nextPage = function() {
	if ( this.pagination.indexStart < (this.pagination.totalConversations-this.pagination.pageSize) ) {
		this.pagination.indexStart += this.pagination.pageSize;
		this.doUpdateMessages();
	}
};

/**
 * Finish the initialization after the DOM is loaded.
 * @return
 */
com.foreclosure.MessagesController.prototype.initUser = function() {
	dojo.subscribe("messagesPane", this,  function(isShown){
		if ( isShown) {
			if ( this.visible ) {return;} 
			this.visible=true;
			this.updateMessages();
		} else {
			this.visible = false;
		}
	});
	
	
	this.pagination.linkEvents();
	
	// connect the form to create new messages
	var form = dojo.byId('newMessage1');

	if ( form ) {
		dojo.connect( form,'onsubmit', this, function(evt) {
			dijit.byId('newForumMessage').hide();
			dojo.stopEvent(evt);
			var form2 = evt.target;
			if ( !form2  ) {
				return;
			}
			var content = {
					title:form2.elements.title.value, 
					content: form2.elements.content.value,
					categoryId: this.categoryId
					};
			this.createMessage(content);
		});
	}
	
	// use pub-sub to get address change notifications
	dojo.subscribe("addressChanged", this, this.onAddressChanged);
	
};

/**
 * Fetch categories from 
 * @return
 */
com.foreclosure.MessagesController.prototype.fetchCategories = function() {
	dojo.xhr({
        url: ACTION.forum.listCategories,
        content: content,
        handleAs:"json-comment-filtered",
        me:this,
        load: function(data, ioArgs) {
           ioArgs.args.me.handleCategoriesResults(data);
        },
        error: showError
    });
};

com.foreclosure.MessagesController.prototype.handleCategoriesResults = function(data) {
	this.categories = data.categories; 
	alert( "got categories " + this.categories );
};

/**
 * Fetch new messages from the backend, do not update if no boundary changes.
 * @param bounds
 * @return
 */
com.foreclosure.MessagesController.prototype.updateMessages = function() {
	if ( typeof searchControl != "undefined" ) {
		this.lastAddress = searchControl.selectedAddress;
		this.lastBounds = searchControl.lastListingBounds;
		this.radius = searchControl.messageStatus.radius;
	}
	this.doUpdateMessages();
};


	
/**
 * Query the backend for new messages.
 * @return
 */
com.foreclosure.MessagesController.prototype.doUpdateMessages = function() {
	var content = {};
	if ( this.lastBounds ) {
	 content = {
    		nelat: this.lastBounds.nelat, nelon: this.lastBounds.nelon,
    		swlat: this.lastBounds.swlat, swlon: this.lastBounds.swlon,
    		radius: this.radius
    	};
	} 
	content.categoryId = this.categoryId;
	content.conversationStart = this.pagination.indexStart;
	content.conversationCount = this.pagination.pageSize;

	dojo.xhrPost(  {
        url: ACTION.forum.listMessages,
        content: content,
        handleAs:"json-comment-filtered",
        me:this,
        load: function(data, ioArgs) {
           ioArgs.args.me.handleSearchResults(data);
        },
        error: showError
    });

};

function initDateFromServerTime( serverTime, date ) {
	if ( date === undefined ) {
		date = new Date();
	}
	var split = serverTime.split('T');
	if ( !split || split.length != 2 ) {
		return undefined;
	}
	var dateParts = split[0].split("-");

	date.setFullYear(dateParts[0]);
	date.setMonth(dateParts[1]-1);
	date.setDate(dateParts[2]);
	
	dateParts = split[1].split(":");
	date.setHours(dateParts[0]);
	date.setMinutes(dateParts[1]);
	date.setSeconds(dateParts[2]);
	return date;
}

com.foreclosure.MessagesController.prototype.formatAsAge = function(date) {
	/*// use the server time to compute the age
	var offset = date.getTimezoneOffset();
	offset = offset-(7*60);
	*/
	var now =this.serverTime;
	
	var post = date.getTime();
	
	// compute the different in minutes
	var diff = (now - post)/60000;
	if ( diff<0 ) {
		diff=0;
	}
	var min = Math.floor(diff % 60);
	var hours = Math.floor((diff / 60) % 24); 
	var days = Math.floor(diff / 1440);
	if ( days > 0 ) {
		return days + " days, " + hours + " hours";
	}
	if ( hours > 0 ) {
		return hours+":" + (min<10?"0":"") + min + " hours";
	}
	return min + " mins";
};

/**
 * Traverse all the conversations and messages
 */
traverseConversations = function ( cs, conversationCallBack, messageCallBack ) {
	if ( !cs || !cs.length  ) {
		return;
	}
	if ( typeof(conversationCallBack) != "function" ) {
		console.log("Wrong conversation callback");
		return;
	}
	if ( typeof(messageCallBack) != "function" ) {
		console.log("Wrong message callback");
		return;
	}
	for ( var ci=0; ci<cs.length;ci++ ) {
		if( !conversationCallBack.call( undefined, cs[ci]) ) {
			return;
		}
		var ms=cs[ci].messages;
		for( var mi=0;mi<ms.length;mi++) {
			var m = ms[mi];
			if ( !messageCallBack.call(undefined, cs[ci], m) ) {
				return;
			}
		}
	}
};

com.foreclosure.MessagesController.prototype.traverseConversations = function( conversationCallBack, messageCallBack ) {
	traverseConversations(this.conversations, conversationCallBack, messageCallBack);
};

/**
 * Display one message in the display array.
 * @param message
 * @param displayArray
 * @return
 */
com.foreclosure.MessagesController.prototype.displayOneMessage = function(message,displayArray, title) {
	var d=displayArray.length;

	displayArray[d++]="<div class='surroundit'>";
	displayArray[d++]="<div class='";
	displayArray[d++]=(title?'conversationInfo':'conversationMessageInfo');
	displayArray[d++]="' id='message";
	displayArray[d++]=message.id;
	displayArray[d++]="'>";
	if ( message.state!="Moderated" && this.adminUser && typeof(messagesAdmin) != "undefined" ) {
		displayArray[d++]="<div class='messagePending' id='ok";
		displayArray[d++]=message.id;
		displayArray[d++]="'>";
		if ( message.conversation.category.moderationStatus == "Public") {
			displayArray[d++]="Public ";
		} else {
			displayArray[d++]="<a href='#' onClick='messagesAdmin.acceptMessage(";
			displayArray[d++] = message.id;
			displayArray[d++] = ")'>Approve</a>&nbsp;";
		}
		displayArray[d++]="<a href='#' onClick='messagesAdmin.rejectMessage(";
		displayArray[d++] = message.id;
		displayArray[d++] = ")'>Reject</a>";
		displayArray[d++] = "</div>";
	} 
	if  (message.state!="Moderated") {
		if ( !this.adminUser && this.requireModeration ) {
			// the current user sees this message only because they are the owner
			displayArray[d++] = "<div class='messagePending'>";
			if ( message.state == "Deleted" ) {
				displayArray[d++] = "Deleted";
			} else {
				displayArray[d++] = "Pending";
			}
			displayArray[d++] = "</div>";
		}
	}
	
	displayArray[d++]="Posted By:";	
	
	displayArray[d++] ="<h5>";
	displayArray[d++]=(message.user.username.length>22)?(message.user.username.substr(0,19)+"..."):message.user.username;
	displayArray[d++]="</h5>";
	var date = initDateFromServerTime(message.editTime);
	displayArray[d++]=this.formatAsAge( date ) + ' ago';
	displayArray[d++]="<span class='conversationDate'>on ";
	displayArray[d++] = date.toString().substr(0,21);
	displayArray[d++]=" </span>";
	displayArray[d++]="</div>";
	displayArray[d++]="<div class='conversationMessage'>";
	if ( title ) {
		displayArray[d++]="<h3>";
		displayArray[d++]=title;
		displayArray[d++]="</h3>";
	}
	if ( message.conversation.address && message.conversation.address.lat ) {
		displayArray[d++] = "<div style='float:right'>";
		displayArray[d++] = "<a href='search.do";
		displayArray[d++] = "?requestedAddress.latitude=";
		displayArray[d++] = message.conversation.address.lat;
		displayArray[d++] = "&requestedAddress.longitude=";
		displayArray[d++] = message.conversation.address.lon;
		displayArray[d++] = "'>Map It</a>";
		displayArray[d++] = "</div>";
		displayArray[d++] = "<div style='clear:both'></div>";
	}
	if ( message.message ) {
		displayArray[d++]=message.message.replace(/\n/g,"<br />");
	} else {
		displayArray[d++]="&nbsp;";
	}
	displayArray[d++]="</div>";
	displayArray[d++]="</div>";
	return displayArray.length;
};

/**
 * Display all the conversations. For now this function generates html.
 * @return
 */
com.foreclosure.MessagesController.prototype.displayConversations = function (ui) {
	var disp=[],d=0; // build the display html in array (standard IE speedup trick)
	var displayReplyLink = ACTION.forum.createMessage && typeof(MESSAGES_ADMIN_MODE)=="undefined";
	for( var ci=0;ci<this.conversations.length;ci++) {
		var c=this.conversations[ci];
		var isFocused = ( c.id == this.focusedId );
		if ( c.messages.length > 0 ) {
			d = this.displayOneMessage(c.messages[0], disp, c.title);
		}
		disp[d++]="<div class='conversationReply'>";
		if ( c.messages.length > 1 ){
			disp[d++] ="<span class='conversationHud'><a href='#' onclick='messagesController.expand(\"messages"+c.id+"\")'>See ";
			disp[d++]=c.messages.length-1;
			disp[d++]=" replies</a></span>";
			disp[d++]="Most recent: ";
			var date = initDateFromServerTime(c.lastEditTime);				
			disp[d++]=this.formatAsAge(date) + " ago";
		} else {			
			if ( displayReplyLink ) {
				disp[d++]="<a href='#' onclick='messagesController.activateReply(this,"+c.id+")'>Write first reply</a>";
			}
		}
		disp[d++]="</div>";
		disp[d++]="<div class='conversationCollapsed'>";
		disp[d++]="<div id='messages"+c.id+"' style='display:";
		disp[d++]= (isFocused && c.messages.length>1)  ? "inline": "none";
		disp[d++]="'>";
		for( var mi=1;mi<c.messages.length;mi++) {
			var m=c.messages[mi];
			d = this.displayOneMessage(m, disp);
		}
		if ( displayReplyLink ) {
			disp[d++]="<div id='replyUI"+c.id+"' class='conversationReply'><a href='#' onclick='messagesController.activateReply(this,"+c.id+")'>Write reply</a></div>";
		} else {
			disp[d++]="<div class='conversationReply'></div>";
		}
		disp[d++]="</div></div>";
	}
	ui.innerHTML = disp.join('');
	
};

/**
 * Handle json return.
 * @param data
 * @return
 */
com.foreclosure.MessagesController.prototype.handleSearchResults = function(data) {
	
	var ui = document.getElementById('messagesPane_existingMessages');
	//ui = dojo.query("fts-topics[data_id]")
	this.conversations = data.conversations;
	this.pagination.totalConversations = data.totalConversations;
	this.serverTime = initDateFromServerTime(data.serverTime);
	this.adminUser = data.adminUser;
	this.requireModeration = data.requireModeration;
	if ( this.conversations === undefined
			|| this.conversations === null
			|| this.conversations.length === undefined 
			|| this.conversations.length === 0 ) {
		ui.innerHTML = "There are no messages at this time.";
	} else {
		this.displayConversations(ui);
		this.pagination.display();
		// move the scrollbar so that the proper entry is focused
		if ( this.focusedId ) {
			var wantedFocus = document.getElementById('replyUI'+this.focusedId);
			if ( wantedFocus ) {
				var scrollbarHolder = document.getElementById('messagesPane');
				scrollbarHolder.scrollTop = wantedFocus.offsetTop-200;
			}
		}
	}	
};

/**
 * UI function, expand the messages for this discussion
 * @param a
 * @return
 */
com.foreclosure.MessagesController.prototype.expand = function(a) {
	var wantedDiv = document.getElementById(a);
	if ( wantedDiv.style.display == 'none') {
		wantedDiv.style.display='inline';
	} else {
		wantedDiv.style.display='none';
	}
};

/**
 * Show the UI for handling a reply.
 * @param ui
 * @param conversationId
 * @return
 */
com.foreclosure.MessagesController.prototype.activateReply = function(ui,conversationId) {
	this.focusedId = conversationId;
	var wantedDiv = ui.parentNode;
	var existingReply = document.getElementById('replyUI');
	if ( existingReply ) {
		if ( existingReply.parentNode == wantedDiv ) {
			// we are already on reply on this node, just minimize it
			existingReply.parentNode.removeChild(existingReply);
			return;
		}
		// clear the previous reply
		existingReply.parentNode.removeChild(existingReply);
		existingReply=null;
	}
	var newEl = document.createElement("div");
	newEl.classStyle = 'conversationMessage';
	newEl.id = 'replyUI';
	var d=[],di=0;
	d[di++]="<form name='replyUI' onsubmit='return messagesController.handleUiReply(this,";
	d[di++]=conversationId;
	d[di++]=")'>";
	d[di++]="<textarea name='content' cols='50' rows='6'></textarea>";
	d[di++]="<br><input type='submit' value='Post'>"; 
	d[di++]="</form>";
	newEl.innerHTML = d.join('');
	wantedDiv.appendChild(newEl);
	document.forms.replyUI.elements.content.focus();
};
	

/**
 * UI event handler called when the user submits a reply.
 * @param ui
 * @return
 */
com.foreclosure.MessagesController.prototype.handleUiReply = function(ui,conversationId) {
	var form = ui;
	var content = { conversationId: conversationId, content: form.elements.content.value, categoryId:this.categoryId };
	this.createMessage(content);
	return false;
};


/**
 * Reset the local state used during editing.
 * @return
 */
com.foreclosure.MessagesController.prototype.clearEditState = function() {
	this.activeConversation = null;
	var titleEl = dojo.byId('newMessage1Title');
	titleEl.value = '';
	titleEl.disabled = false;
	dojo.byId('newMessage1Content').value = '';
};

/**
 * Call the backend to create a new message.
 * @param evt
 * @return
 */
com.foreclosure.MessagesController.prototype.createMessage = function(content) {
	if ( this.lastBounds ) {
		content.lng = (this.lastBounds.nelon + this.lastBounds.swlon)/2;
		content.lat = (this.lastBounds.nelat + this.lastBounds.swlat)/2;
	} else if ( this.lastAddress ) {
		content.lng = this.lastAddress.longitude;
		content.lat = this.lastAddress.latitude; 
	} 
    dojo.xhrPost(  {
        url: ACTION.forum.createMessage,
        content: content,
        handleAs:"json-comment-filtered",
        me:this,
        load: function(data, ioArgs) {
           ioArgs.args.me.handleNewMessageResponse(data);
        },
        error: showError
    });
	this.clearEditState();
};

com.foreclosure.MessagesController.prototype.showCategory = function(categoryId) {
	this.categoryId = categoryId;
	this.pagination.indexStart = 0;
	this.doUpdateMessages();
};

/**
 * Handle the return from creating a new message.
 * @param data
 * @return
 */
com.foreclosure.MessagesController.prototype.handleNewMessageResponse = function(data) {
	if ( data.actionErrors && data.actionErrors.length > 0 ) {
		alert( "There was a problem creating your message:\n" + data.actionErrors[0] );
		return;
	}
	this.clearEditState();
	this.focusedId = data.conversationId;
	this.doUpdateMessages(this.lastBounds);
};

com.foreclosure.MessagesController.prototype.init=function() {
	var params = GeoLib.parseParams();
	if ( params.conversationId ) {
		this.focusedId  = params.conversationId;
	}
	if ( params.categoryId ) {
		this.categoryId = params.categoryId;
		// if we are in global mode then mark as selected
	}
	var categoriesPane = dojo.byId('categoriesPane');
	if ( categoriesPane ) {
		var that = this;
		var selected = dojo.query(".title a", categoriesPane).filter(function(c) {
			if ( c.attributes.data_id && that.categoryId == c.attributes.data_id.value ) {
				return c;
			}
		});
		if ( selected && selected[0] ) {
			this.showMessages(selected[0]);
		}
	} else {
		messagesController.doUpdateMessages();
	}	
};

com.foreclosure.MessagesController.prototype.showMessages = function(node) {
	//dijit.byId("mainTabContainer").selectChild("messagesPane");

	var dataAttribute = node.attributes.data_id;
	if ( !dataAttribute ) {
		return;
	}
	var categoryId = dataAttribute.value;
	dojo.query('.selected', dojo.byId('categoriesPane')).removeClass('selected'); 
	dojo.addClass(node.parentNode, 'selected' );
	this.delegate.showCategory(categoryId);
};

com.foreclosure.MessagesController.prototype.setupUI = function() {
	var ids = [];
	var that = this;
	var categories = dojo.query('.title', dojo.byId('categoriesPane') );
	categories.onclick(function (evt) {
		that.showMessages(evt.target.parentNode);
	});
};

com.foreclosure.MessagesController.prototype.showNewMessageDialog = function() {
	dijit.byId('newForumMessage').show();
};


var messagesController = null;

dojo.addOnLoad( function() {
	if ( messagesController === null ) {
		messagesController = new com.foreclosure.MessagesController();
		messagesController.initUser();
		messagesController.setupUI();
		// switch the focus to our panel if desired
		if ( GeoLib.isPanelActivated("messages") ) {		
			dijit.byId("mainTabContainer").selectChild("messagesPane");
			messagesController.init();
		} else {
			if ( typeof(MESSAGES_ADMIN_MODE) != "undefined" && MESSAGES_ADMIN_MODE) {
				return;
			}
			var categories = dojo.query('.title', dojo.byId('categoriesPane') );
			if ( categories && categories.length ) {
				messagesController.showMessages(categories[0].firstChild);
			}
		}
	}
});