/*
 * xhr namespace
*/
if (typeof(xhr) == "undefined") xhr = {};


/*
 * This class is used to manage page comments using AJAX (asynchronous
 * javascript and xml). There are also a set of helper functions that
 * manage instantiation and page related html to create the dynamic
 * look-and-feel.
 * 
*/
xhr.Comments = function() {
	this.url = "retrieve_live_updates.php";	// pointer to server page to process AJAX request
	this.divComments;						// holds entire comments html string
	this.charWidth = 400;					// number of chars before more
	this.Comment;

    // private global vars used by class methods
	var xmlhttp;							// holds xmlhttprequest object
	var url;								// holds this.url
	var ts = "";							// timestamp sent back from server
	var LastMaintained;						// time last record was maintained is returned from the server
	var div;								// needed for callback
	var charWidth;							// for callback -- number of chars before more
	var needSound = 0;						// used to trigger a sound each time the screen is updated

	// set the xmlhttprequest object
    if (window.XMLHttpRequest) {
        try {
            xmlhttp = new XMLHttpRequest();
        } catch (e) {
            xmlhttp = false;
        }
    } else if (window.ActiveXObject) {
        try {
            xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {
                xmlhttp = false;
            }
        }
    }

    // privileged methods

    // is this browser capable of xmlHttpRequest?
    this.isBrowserXmlHttpCapable = function() {
        return (xmlhttp) ? true : false;
    }

    // set div where comments are to be displayed
    this.setCommentsDiv = function(d) {
        if (typeof(d) == "undefined") {
            d = "Comments";
        }

        this.divComments = document.getElementById(d);

        if (!xmlhttp) {
            return false;
        } else if (this.divComments) {
            this.divComments.innerHTML =  this.innerHTML;     // set div contents
            this.divComments.className = "visible";           // make comments UI visible if divComments exists

            // div where comments are to be displayed
            div = document.getElementById("entries");
            charWidth = this.charWidth;
        } else {
            alert('Comments class requires that \n\n<div id="Comments" class="invisible"></div>\n\n be defined in the HTML file.');
        }
    }

    // Get comments from the server
    this.getComments = function() {
        url = this.url;
        _sendRequest();
    }

    // private methods 
    var _sendRequest = function() {
        xmlhttp.abort();
        xmlhttp.open("POST", url, true);
        xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        xmlhttp.setRequestHeader("Accept","text/xml");
        xmlhttp.onreadystatechange = _CommentCallBack;
        xmlhttp.send("method=get&ts=" +ts);
    }

    // Server results are processed here.
    var _CommentCallBack = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            var Comment = "";
            var xml = xmlhttp.responseXML;

            if (xml != null && xml.getElementsByTagName("results").item(0) != null) {
                var a = xml.getElementsByTagName("results").item(0);
                // update timestamp
                ts = a.getAttribute("ts");

                if (typeof(LastMaintained) == "undefined") {
                    LastMaintained = a.getAttribute("LastMaintained");
                } else {
                    if (LastMaintained != a.getAttribute("LastMaintained")) {
//						refresh if LastMaintained is > ts
						LastMaintained = a.getAttribute("LastMaintained");
						if (LastMaintained > ts) {
							div.innerHTML = "Updating...";
							ts = "";
//							don't wait for timeout!!!!
							_c_.getComments();
						}
					}
                }

				var Comments = xml.getElementsByTagName("Comment");
				var html = _updateCommentList(Comments);
				if (html) {
//					needed for LastMaintained logic
					if (div.innerHTML == "Updating...") {
						div.innerHTML = "";
						needSound = 1;
					}
					div.innerHTML = html +div.innerHTML;
//					play sound once if updating the screen
					needSound++;
					if (needSound == 2) {
						div.innerHTML += "<embed src='live_update.wav' autostart=true width=0 height=0 name='sound1' enablejavascript='true'>";
					}
				}
			}
		}
	}

    // creates html containing Comments
	var _updateCommentList = function(Comments) {
		var Comment = "";
		for (i = 0; i < Comments.length; i++) {
			var n = Comments.item(i).childNodes;
			if (n.item(1).childNodes.item(0)) {
				var text = n.item(1).childNodes.item(0).nodeValue;
				text = text.replace(/\n/g, '<br />');
				var Course = "all";
				if (n.item(0).childNodes.item(0)) {
					Course = n.item(0).childNodes.item(0).nodeValue;
				}
				var timestamp = n.item(2).childNodes.item(0).nodeValue;
				var intMatch = timestamp.indexOf(" ");

				var date = timestamp.substr(0, intMatch);
				var yyyy = date.substr(0, 4);
				var mm = date.substr(5, 2);
				var dd = date.substr(8, 2);
				date = mm +"/" +dd +"/" +yyyy;

				var time = timestamp.substr(intMatch+1, timestamp.length - intMatch);

				Comment += "<div class='by'>" +" <span class='date x-small'>" +date +"&nbsp; " +time +"</span>" +"</div>";
				Comment += "<div>";
				if (text.length > charWidth) {
					var teaser = text.substr(0, charWidth);
					Comment += "<div id='text' class='para'><span>" +teaser + "... " +"</span><span class='invisible'>" +text +" " +"</span><a class='darkgraycol' href='javascript:void(0);' onclick='xhr.Comments.prototype.more(this)' title='more'><img src='/images/br.gif' width='21' height='13'></a></div>";
				} else {
					Comment += "<div class='para'>" +text +"</div>";
				}

				Comment += "<span class='pad'>&nbsp;</span>";
				Comment += "</div>";
			}
		}
		return Comment;
	}
}

xhr.Comments.prototype = {
    // public vars and methods

    innerHTML: 
        "<div id='lc'>" +
        " <div id='titleCap'><span id='title'>Live Updates</span></div>" +
        " <div id='entries'></div>" +
        " <span id='so'>&nbsp;</span>" +
        "</div>",

    // every object has a toString, so what is this class?
    toString:function() {
        return "Class to manage page comments using AJAX.";
    },

    // special UI expand routine (more/less)
	more:function(o) {
		o.blur();
		o.firstChild.src = "/images/bl.gif";
		o.title = "less";
		var self = this;
		o.onclick = function() {self.less(this)};
		var p = o.parentNode;
		p.childNodes[0].className = "invisible";
		p.childNodes[1].className = "visible";
	},

    // reset more
	less:function(o) {
		o.blur();
		o.firstChild.src = "/images/br.gif";
		o.title = "more";
		var self = this;
		o.onclick = function() {self.more(this)};
		var p = o.parentNode;
		p.childNodes[0].className = "visible";
		p.childNodes[1].className = "invisible";
	}
}

/*
 * General helper functions that use Comments class.
*/

// initalizes Comments class and sets instance and global vars
function initComments(refreshSeconds) {
//	initComments should be passed the refresh rate in seconds (default is 60)
	if (typeof(refreshSeconds) != "undefined") {
		refreshRate = refreshSeconds * 1000;
	} else {
		refreshRate = 60000;
	}
	_c_ = new xhr.Comments;
	_c_.setCommentsDiv();
	if (_c_.divComments && _c_.isBrowserXmlHttpCapable()) {
		getComments();        // start recursive loop watching for new comments
	} else if (_c_.divComments) {
		_c_.divComments.className = "visible";
	}
}

// loop getting new comments from server
function getComments() {
	_c_.getComments();
	setTimeout(getComments, refreshRate); // recursive loop
}
