/* blog.js 
* Author: Mehmud Abliz
* (c) All rights reserved.
*/

// blog title
blogTitle = "Mehmud's Research Blog";

//timeout settings
showNoticeTime = 5000;				// 5 seconds

// URLs
blogMainURL = "main.php";
blogNavURL = "nav.php";

// JSON data types
JSON_APP_ERROR = 1;
JSON_APP_NOTICE = 2;
//JSON_LOGIN_STATUS = 3;
//JSON_REGISTER_STATUS = 4;
JSON_CAT_LIST = 5;
JSON_POST = 6;
JSON_COMMENT = 7;
JSON_POSTS = 8;
JSON_COMMENTS = 9;

// Login status codes
//LOGIN_NOT = 0;
//LOGIN_JUST = 1;
//LOGIN_ALREADY = 2;

//other globals
//loginSalt = null;

/* preload images*/
var preloadImages = ["img/loading.gif", "img/info.png", "img/warning.png"];
for(var i = 0; i < preloadImages.length; i++) {
	var oImg = new Image();
	oImg.src = preloadImages[i];
}

/*-------------------------------------------------------
 * The blog object.
 *-------------------------------------------------------*/

var blog = {
		processing: false,
		prevPage: 0,
		nextPage: 0,
		
		init: function() {
			var allElements = document.getElementsByTagName("*");
			if(!allElements.length) {
				allElements = document.all;
			}
			
			for(var i=0; i < allElements.length; i++) {
				if(allElements[i].id.length > 0) {
					this[allElements[i].id] = allElements[i];
				}
			}
			
			this.iLoader.onload = function() {
				blog.iFrameCheckError();
			};
			this.spnSubmitSearch.onclick = function() {
				blog.searchBlog();
			};
			this.liHomeLink.onclick = function() {
				blog.dispHome();
			};
			this.liRSSLink.onclick = function() {
				window.open('http://feeds.feedburner.com/MehmudsBlog'); 
			};
			this.frmSearch.onsubmit = function() {
				blog.searchBlog();
				return false;
			};
			this.spnNavOlder.onclick = function() {
				blog.dispPosts(blog.nextPage);
			};
			this.spnNavNewer.onclick = function() {
				blog.dispPosts(blog.prevPage);
			};
		},
		
		load: function() {
			this.init();
			this.dispHome();
		},
		
		dispNotice: function(jsonObj, dispAsInfo, noticeTime, div) {
			var divNotice;
			if(div) {
				divNotice = div;
			} else {
				divNotice = this.divNotice;
			}
			divNotice.innerHTML = "";
			var time2disp = showNoticeTime;
			if(noticeTime > 1000) {
				time2disp = noticeTime;
			}

			if(typeof(jsonObj.msg) == 'array') {
				var innerHtml = "<ul>";
				for (var i = 0; i < jsonObj.msg.length; i++) {
					innerHtml += "<li>" + jsonObj.msg[i] + "</li>";
				}
				innerHtml += "</ul>";
				divNotice.innerHTML = innerHtml;
			} else {
				divNotice.innerHTML = jsonObj.msg;
			}
			divNotice.className = "error";
			
			if(dispAsInfo || (jsonObj.type == JSON_APP_NOTICE)) {
				divNotice.className = "info";
			}
			this.showBusy(false);
			divNotice.style.display = "block";
			window.scroll(0,0);
			setTimeout(function () {divNotice.style.display = "none";}, time2disp);
		},
		
		displayNone: function() {
			this.divContentWrapper.style.display = "none";
			this.divNotice.style.display = "none";
		},
		
		dispHome: function() {
			this.displayNone();
			this.divContentWrapper.style.display = "block";
			this.setProcessing(false);
			this.showBusy(true);
			var url = blogNavURL+ "?m=Blog&a=showHome";
			this.nav(url);
			this.showBusy(false);
		},
		
		dispCategories: function() {
			var url = blogNavURL+ "?m=Blog&a=showAllCategories";
			this.nav(url);
			this.setProcessing(false);
		},
		
		dispPosts: function(start) {
			var url = blogNavURL + "?m=Blog&a=showPosts&startPage=" + start;
			this.nav(url);
			this.setProcessing(false);
		},
		
		dispPostsByCategory: function(elem) {
			var url = blogNavURL + "?m=Blog&a=showPostsByCategory&name=" + encodeURIComponent(elem.innerHTML);
			this.nav(url);
			this.setProcessing(false);
		},
		
		dispPostsByTag: function(elem) {
			var url = blogNavURL + "?m=Blog&a=showPostsByTag&tag=" + encodeURIComponent(elem.innerHTML);
			this.nav(url);
			this.setProcessing(false);
		},
		
		dispPostsByArchive: function(elem) {
			var date = (elem.innerHTML).split(" ");
			var url = blogNavURL + "?m=Blog&a=showPostsByArchive";
			url += "&month=" + date[0] + "&year=" + date[1];
			this.nav(url);
			this.setProcessing(false);
		},
		
		dispPost: function(elem) {
			var url = blogNavURL + "?m=Blog&a=showPost&title=" + encodeURIComponent(elem.innerHTML);
			this.nav(url);
			this.setProcessing(false);
		},
		
		dispPostMore: function(titleTagId) {
			title = document.getElementById(titleTagId).innerHTML;
			var url = blogNavURL + "?m=Blog&a=showPost&title=" + encodeURIComponent(title);
			this.nav(url);
			this.setProcessing(false);
		},

		iFrameCheckError:function() {
			var iTitle = this.iLoader.contentWindow.document.title;
			if(iTitle == "") {
				var errJsonStr = this.iLoader.contentWindow.document.body.innerHTML;
				var jsObj = JSON.parse(errJsonStr);
				this.handleReply(jsObj);
			}
		},
		
		searchBlog:function() {
			var searchWord =  this.inSearchFor.value;
			var url = blogNavURL + "?m=Blog&a=findPost&word=" + encodeURIComponent(searchWord);
			this.nav(url);
			this.frmSearch.reset();
			this.setProcessing(false);
		},
		
		addComment: function() {
			var form = document.getElementById("frmLeaveComment");
			var postData = getFormData(form);
			postData += "&challenge=" + Recaptcha.get_challenge();
			postData += "&response=" + Recaptcha.get_response();
			var url = blogMainURL + "?m=Blog&a=addComment";
			this.request(url, postData, false, blog.handleReply);
			this.setProcessing(false);
		},
		
		showHomePage: function(posts) {
			if(posts.type == JSON_POSTS) {
				this.showPosts(posts);
				this.showTags(posts.allTags);
				this.showCategoryList(posts.categories);
				this.showArchives(posts.archives);
				document.title = "Home | " + blogTitle;
				this.setProcessing(false);
			} else {
				this.dispNotice(posts);
			}
		},
		
		showPosts: function(posts) {
			document.title = "Posts | " + blogTitle;
			var html = "";
			var postCount = posts.msg.length;
			for(var i = 0; i < postCount; i++) {
				html += "<div class='divBlogPost'>\n";
				html += "<h3 class='divBlogPostTitle link' id='post" + i + "' onclick='blog.dispPost(this)'>" + 
						posts.msg[i].title + "</h3>\n";
				html += "<div class='divDateAndComment'>\n";
				html += "<span class='spnPostedDate'>" + posts.msg[i].posted + "</span>\n";
				html += "<span class='spnNumOfComment'>" + posts.msg[i].numComments + " comment(s)</span>\n";
				html += "</div>\n";
				html += "<div class='divPostTag'>\n";
				var tagCount = posts.msg[i].tags.length;
				var tags = posts.msg[i].tags;
				var spans = new Array();
				for(var j=0; j < tagCount; j++) {
					spans.push("<span class='link' onclick='blog.dispPostsByTag(this)'>" + tags[j] + "</span>");
				}
				html += spans.join(", ");
				html += "\n</div>\n";
				
				html += "<div class='divAbstract'>\n" + posts.msg[i].abstract + 
						" ... <span class='link' onclick='blog.dispPostMore(\"post" + i + "\")'>more &#187;</span>\n</div>\n";
				html += "</div>\n";
			}
			
			this.divPageNav.style.display = "none";
			this.prevPage = posts.prevPage;
			this.nextPage = posts.nextPage;
			
			this.divMainContent.innerHTML = html;
			
			if(posts.prevPage == posts.currPage) {
			// if(posts.prevPage == 0) { /* this does not work for 2nd page!*/
				this.spnNavNewer.style.display = "none";
			} else {
				this.spnNavNewer.style.display = "block";
				this.divPageNav.style.display = "block";
			}
			// if(posts.nextPage == posts.currPage || posts.prevPage == posts.nextPage) {
			if(posts.nextPage == 0) {
				this.spnNavOlder.style.display = "none";
			} else {
				this.spnNavOlder.style.display = "block";
				this.divPageNav.style.display = "block";
			}
			
			window.scroll(0,0);
		},
		
		showPost: function(post) {
			document.title = htmlEntity2Char(post.title) + " | " + blogTitle;
			var html = "";
			
			html += "<div class='divBlogPost'>\n";
			html += "<h3 class='divBlogPostTitle'>" + post.title + "</h3>\n";
			html += "<div class='divDateAndComment'>\n";
			html += "<span class='spnPostedDate'>" + post.posted + "</span>\n";
			html += "<span class='spnNumOfComment'>" + post.numComments + " comment(s)</span>\n";
			html += "</div>\n";
			html += "<div class='divPostTag'>\n";
			var tagCount = post.tags.length;
			var tags = post.tags;
			var spans = new Array();
			for(var j=0; j < tagCount; j++) {
				spans.push("<span class='link' onclick='blog.dispPostsByTag(this)'>" + tags[j] + "</span>");
			}
			html += spans.join(", ");
			html += "\n</div>\n";
			html += "<div class='divPostBody'>\n" + post.body + "\n</div>\n";
			html += "<div id='divComments'>\n";
			html += "<h3>Comments</h3>\n";
			var commCount = post.comments.length;
			for(var i=0; i < commCount; i++) {
				html += "<div class='divCommentorAndDate'>\n";
				html += "<span class='spnCommentor'>" + post.comments[i].commenter + "</span>";
				html += "<span>" + post.comments[i].posted + "</span>";
				html += "</div>\n";					/* End of divCommentorAndDate */
				html += "<div class='divComment'><p>" + formatComment(post.comments[i].content) + "</p></div>";
			}
			html += "</div>\n";				/* End of divComments */
			html += "<div id='divLeaveComment'>\n";
			html += "<h3>Leave A Comment</h3>\n";
			html += "<form method='post' id='frmLeaveComment'>\n";
			html += "<table>\n";
			html += "<tr><td>Name: </td><td><input type='text' id='inCommenter' name='inCommenter' value='' /></td></tr>";
			html += "<tr><td>Comment:</td><td><textarea id='taComment' name='taComment' cols='68' rows='10'></textarea>";
			html += "<textarea class='hidden' id='inPostTitle' name='inPostTitle'>" + post.title + "</textarea></td></tr>";
			html += "<tr><td></td><td id='recaptcha_div'></td></tr>";
			html += "<tr><td></td><td><span class='link submitButton' id='spnSubmitComment' onclick='blog.addComment();'>Submit</span></td></tr>";
			html += "</table>\n";
			html += "</form>\n";
			html += "</div>\n";				/* End of divLeaveComment */
			html += "</div>\n";	/* End of divBlogPost */
			
			this.divPageNav.style.display = "none";
			this.divMainContent.innerHTML = html;
			Recaptcha.create("6LcHpAgAAAAAAJocLmCEaG8_uekXC88R4wJ0NpA4",
					"recaptcha_div", {theme: "white"});
			window.scroll(0,0);
		},
		
		showCategoryList: function(catList) {
			var html = "";
			var listLength = catList.length;
			
			html += "<li class='link' onclick='blog.dispCategories()'>All categories</li>";
			for(var i = 0; i < listLength; i++) {
				html += "<li class='link' onclick='blog.dispPostsByCategory(this)'>" + catList[i] + "</li>";
			}
			this.ulCategoryList.innerHTML = html;
		},
		
		showTags: function(tags) {
			var divTags = this.divTagContainer;
			var html = new Array();
			for(var i = 0; i < tags.length; i++) {
				html.push("<span class='link' onclick='blog.dispPostsByTag(this)'>" + tags[i] + "</span>");
			}
			divTags.innerHTML = html.join(", ");
		},
		
		showArchives: function(archives) {
			var html = "";
			var arcLength = archives.length;
			for(var i=0; i < arcLength; i++) {
				html += "<li class='link' onclick='blog.dispPostsByArchive(this)'>" + archives[arcLength-1-i] + "</li>\n";
			}
			this.ulArchiveList.innerHTML = html;
		},
		
		showCategories: function(categories) {
			document.title = "Categories | " + blogTitle;
			var html = "";
			var catCount = categories.msg.length;
			for(var i = 0; i < catCount; i++) {
				html += "<div class='divBlogPost'>\n";
				html += "<h3 class='divBlogPostTitle link' onclick='blog.dispPostsByCategory(this)'>" + categories.msg[i].name + "</h3>\n";
				html += "<div class='divDateAndComment'>\n";
				html += "<span class='spnPostedDate'>" + categories.msg[i].posted + "</span>\n";
				html += "</div>\n";
				html += "<div class='divPostBody'>\n" + categories.msg[i].description + "\n</div>\n";
				html += "</div>\n";
			}
			
			this.divPageNav.style.display = "none";
			this.divMainContent.innerHTML = html;
		},
		
		showComment: function(comment) {
			
			var commentsDiv = document.getElementById("divComments");
			var html = "";
			
			html += "<div class='divCommentorAndDate'>\n";
			html += "<span class='spnCommentor'>" + comment.commenter + "</span>";
			html += "<span>" + comment.posted + "</span>";
			html += "</div>\n";
			html += "<div class='divComment'><p>" + formatComment(comment.content) + "</p></div>";
			
			commentsDiv.innerHTML += html;
			Recaptcha.reload();
		},
		
		handleReply: function(jsObj) {
			switch(jsObj.type) {
			case JSON_APP_ERROR:
			case JSON_APP_NOTICE:
				blog.dispNotice(jsObj);
				break;
			case JSON_POST:
				blog.showPost(jsObj);
				break;
			case JSON_POSTS:
				blog.showPosts(jsObj);
				break;
			case JSON_CAT_LIST:
				blog.showCategories(jsObj);
				break;
			case JSON_COMMENT:
				blog.showComment(jsObj);
				break;
			}
		},
		
		setProcessing: function (bProcessing) {
	        this.processing = bProcessing;
	    },
		
		nav:function(url) {
	        if (this.processing == true) return;
	        try {
	            this.setProcessing(true);
	            this.iLoader.src = url;
	        } catch (exception) {
	        	var errJsonObj = new JsonObject(JSON_APP_ERROR, exception.message);
	        	this.dispNotice(errJsonObj);
	        }
		},
		
		request:function(url, postData, isSync, handler) {
			if (this.processing == true) return;
			try {
				this.setProcessing(true);
				var xhr = createXHR();
				
				xhr.onreadystatechange = function() {
					try {
						 if (xhr.readyState == 4) {
	                        if (xhr.status == 200) {
	                        	var jsObject = JSON.parse(xhr.responseText);
	                        	handler(jsObject);
	                        	blog.showBusy(false);
	                        } else {
	                            throw new Error("An error occurred while attempting to contact the server.");
	                        }
	                    } else {
	                    	// show busy screen
	                    	blog.showBusy(true);
	                    }
					} catch(exception) {
						var errJsonObj = new JsonObject(JSON_APP_ERROR, exception.message);
						blog.dispNotice(errJsonObj);
					}
				};
				
				var async = true;
				if(isSync == true) {
					async = false;
				}
				
				if(postData) {
					xhr.open("post",url, async);
					xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
					xhr.send(postData);
				} else {
					xhr.open("get",url, async);
					xhr.send(null);
				}
				
				if(!async) {
					var jsObject = JSON.parse(xhr.responseText);
	            	handler(jsObject);
				}
			} catch(exception) {
				var errJsonObj = new JsonObject(JSON_APP_ERROR, exception.message);
	        	this.dispNotice(errJsonObj);
			}
		},
		
		showBusy: function(isOn) {
			if(isOn) {
				this.divLoading.style.display = "block";
				this.divContainer.style.opacity = 0.5;
			} else {
				this.divLoading.style.display = "none";
				this.divContainer.style.opacity = 1;
			}
		}
};


/*-------------------------------------------------------
 * Utility Functions
 *-------------------------------------------------------*/

function getFormData(form) {
    var params = new Array();
    for (var i=0 ; i < form.elements.length; i++) {
    	var frmName = form.elements[i].name;
    	if(typeof frmName == "undefined" || frmName == "") {
    		continue;
    	}
        var param = encodeURIComponent(frmName);
        param += "=";
        param += encodeURIComponent(form.elements[i].value);
        params.push(param);
    } 
    
    return params.join("&");
}

function createXHR() {
	if(typeof XMLHttpRequest != "undefined") {
		return (new XMLHttpRequest());
	} else if(window.ActiveXObject) {
		var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0"];
		for(var i = 0; i < versions.length; i++) {
			try {
				var xhr = new ActiveXObject(versions[i]);
				return xhr;
			} catch (error) {
				var errJsonObj = new JsonObject(JSON_APP_ERROR, error.message);
				blog.dispNotice(errJsonObj);
			}
		}
	}
	throw new Error("Could not create XMLHttp object!");
}

function formatComment(comment) {
	if(comment.length > 0){
		str = comment.replace(/\n/g,'<br/>');
		return str;
	} else {return "";}
}

function htmlEntity2Char (htmlEntity) {
	var div = document.createElement('div');
	div.innerHTML = htmlEntity;
	if (typeof div.innerText != 'undefined')
	{
		return div.innerText;
	}
	else if (typeof div.ownerDocument != 'undefined' &&
			typeof div.ownerDocument.createRange != 'undefined')
	{
		var range = div.ownerDocument.createRange();
		range.selectNodeContents(div);
		return range.toString();
	}
	else if (typeof div.textContent != 'undefined')
	{
		return div.textContent;
	}
}



function JsonObject(type, msg) {
	this.type = type;
	this.msg = msg;
}


// set onload event of window so that blog will be loaded when 
// the page has completed loading
window.onload = function() {
	blog.load();
};
