// script to track read/unread comments through a cookie
// based very loosely on hokei's code from 
//     http://www.haloscan.com/forum/index.php?showtopic=1384
//
// we track the user's actions by storing the hs array (from haloscan) in 
// source form as the array hl[] in the cookie named cookieName.
// we eval it to unserialize it.

// Constants: cookie name, expiry, size limit (const doesn't work in older js)
var cookieName   = "hlArray";
var cookieExpiry = "; expires=Fri, 01-Jan-2070 00:00:00 GMT";
var cookieLimit  = 3999;

// create a closure around the hl[] array
function makeCookieReader(cookieStr) {
    eval(cookieStr);
    return function (postID) {
        if (typeof hl != 'undefined')
            return hl[postID];
        else
            return null;
    }
}

var postsReadFor = makeCookieReader(getCookieVal(cookieName));

// getCookieVal - get the cookie value of name
function getCookieVal(name) {
    var allCookies = document.cookie;
    var index      = allCookies.indexOf(name + "=");
    if (index == -1)
        return null;

    index      = allCookies.indexOf("=", index) + 1;
    var endstr = allCookies.indexOf(";", index);
    if (endstr == -1)
        endstr = allCookies.length;

    return unescape(allCookies.substring(index, endstr));
}

// trimHlCookieVal - returns a trimmed cookie value that throws out entries at 
//                   the beginning of hl[] unless it's postID.  standard limit 
//                   of cookies is 4000 bytes including cookieName and '='.  
//                   XXX is there a better way of doing this?
function trimHlCookieVal(name, val, expiry, postID) {
    var nameExpiryLength = expiry.length + name.length + 1;
    var destroy          = new RegExp("hl\\[\"(?!" + postID + "\"\\])");
    var start;
    var end;

    while (escape(val).length + nameExpiryLength > cookieLimit) {
        start = destroy.exec(val).index;
        end   = val.indexOf(";", start) + 1;
        val   = val.substring(0,start) + val.substring(end, val.length);
    }
    return val;
}

// setCookieVal - stores a cookie recording the hs array when the user clicks
//                a comments link of a post.  the array is renamed hl
function setCookieVal(postID) {
    // if haloscan's down or its script isn't working properly, return
    if (typeof hs == 'undefined')
        return;

    var cookieStr   = getCookieVal(cookieName);
    var numComments = (typeof hs[postID] == 'undefined' ? 0 : hs[postID]);

    // source representation of hs[postID] to be stored in cookie and eval'ed
    var jsCode = "hl[\"" + postID + "\"]=" + numComments + ";";

    if (cookieStr) {
        // search and replace previously set value for this post
        var re = new RegExp("hl\\[\"" + postID + "\"\\]=\\d+;");
        if (re.test(cookieStr))
            cookieStr = cookieStr.replace(re, jsCode);
        else
            cookieStr += jsCode;

        if (cookieName.length + 1 + escape(cookieStr).length
            + cookieExpiry.length > cookieLimit)
            cookieStr = trimHlCookieVal(cookieName, cookieStr, 
                                        cookieExpiry, postID);
    } else
        cookieStr = "var hl = new Array();" + jsCode;

    cookieStr       = cookieName + "=" + escape(cookieStr) + cookieExpiry;
    document.cookie = cookieStr;
}

// newCheck - writes out the text of how many comments are new or unread
function newCheck(postID) {
    if (typeof hs == 'undefined')
        return;

    var numCommentsThisTime = 
        (typeof hs[postID] == 'undefined' ? 0 : hs[postID]);
    var numCommentsLastTime = 
        (postsReadFor(postID) == null ? 0 : postsReadFor(postID));

    if (numCommentsThisTime > 0) {
      if (numCommentsThisTime > numCommentsLastTime) {
          var numNewComments = numCommentsThisTime 
                               - numCommentsLastTime;
          document.write("&nbsp;&nbsp;&nbsp;[<b>" + numNewComments 
                         + " new opinion"
                         + (numNewComments == 1 ? "" : "s") + ".</b>]");
      } else 
          document.write("&nbsp;&nbsp;&nbsp;[<i>No new opinions.</i>]");
    }
}
