/* ------------------------------------------------------------------------ *
 * SAS Institute, Inc.                                                      *
 *                                                                          *
 * Copyright (c) 2002-2007 SAS Institute, Inc.  All rights reserved.             *
 *                                                                          *
 * Contains classes and functions that allow for easy creation and          *aler
 * and manipulation of cookies.                                             *
 *                                                                          *
 * Dependencies: none                                                       *
 * ------------------------------------------------------------------------ */

// -----------------------------------------------------------------------------i
// wrsCookie class - An class that abstracts the notion of a Cookie so that
// cookies can be manipulated as objects rather than tokens in a string.
//
// NOTE: 85% of this implementation is taken from the Cookie example in
// "JavaScript: The Definitive Guide", 4th Edition, pgs 270-273. However,
// there are noticable differences, namely
//    1) WRS implementation of store() preserves cookies already in document
//    2) WRS implementation provides a completely different way of specifying
//       cookie attributes which are not predefined.
//
// @param documen - Document object for which the cookie is stored. Required.
// @param name    - String that specifies the name of the cookie. Required.
// @param hours   - An optional number that specifies the number of hours
//                  from now after which te cookie should expire.
// @param path    - An optional string that specifies the cookie path attribute.
// @param domain  - An optional string that specifies the cookie domain attribute.
// @param secure  - An optional boolean that, if true, requests a secure cookie.
// -----------------------------------------------------------------------------
wrsProvide("citation_cookie");
wrsRequire("citation",  SCRIPT_DIR, "citation_cookie");

function WRSCookie(doc, name, hours, path, domain, secure)
{
    this.document = doc;
    this.name = name;
    this.expiration  = (hours != null)
                          ? new Date( (new Date()).getTime() + (hours*3600000) )
                          : null;

    this.path = (path != null) ? path : null;
    this.domain = (domain != null) ? domain : null;
    this.secure = (secure != null) ? secure : false;
    this.value = null;
}

//cookie property whose values are Date objects. Values of this property represent
//the date in which the cookie should expire. To delete a cookie simpley use a Date
//that is before todays date or time. You may also use the removeFromDocument() method
//to accomplish the same thing.
WRSCookie.prototype.expiration = null;
WRSCookie.prototype.ATTRIBUTE_DELIM = "&"; //default attribute delimiter in cookie value
WRSCookie.prototype.NAME_VALUE_DELIM = ":"; //default attribute name-value delimiter in cookie value

WRSCookie.prototype.getAttributeMap = function()
{
   if (this.attributeMap == null) {
      this.attributeMap = new Array();
   }
   return this.attributeMap;
}

WRSCookie.prototype.getAttribute = function(attributeName)
{
    return this.getAttributeMap()[attributeName];
}

WRSCookie.prototype.setAttribute = function(attributeName, value)
{
    this.getAttributeMap()[attributeName] = value;
}

WRSCookie.prototype.removeAttribute = function(attributeName)
{
    var attributeMap = this.getAttributeMap();
    delete attributeMap[attributeName];
}

WRSCookie.prototype.store = function()
{
    //assemble value of cookie
    var cookieVal = "";
    var attribMap = this.getAttributeMap();
    var attribCount = 0;
    for (var attribName in attribMap) {
        if (attribCount != 0) { cookieVal += this.ATTRIBUTE_DELIM; }
        cookieVal += ( attribName + this.NAME_VALUE_DELIM + encodeURIComponent(attribMap[attribName]) );
        attribCount++;
    }

    //assemble document cookies preserving any preexisting cookies of same name;
    var cookie = this.name + "=" + cookieVal;
    if (this.expiration) { cookie += ( "; expires=" + this.expiration.toGMTString() ); }
    if (this.path)       { cookie += ( "; path=" + this.path ); }
    if (this.domain)     { cookie += ( "; domain=" + this.domain ); }
    if (this.secure)     { cookie += ( "; secure" ); }

    this.value = cookie;
}

WRSCookie.prototype.initialize = function()
{
    var allCookies = this.document.cookie;
    if (allCookies == "") {
        return false;
    }
    var myCookieDefn = this.extractCookieDefn(allCookies);
    if (myCookieDefn == null) {
        return false;
    }

    //cookie val = substring after name and equals sign
    var myCookieVal = myCookieDefn.substring(this.name.length + 1);

    //break cookie down into individual attributes
    // a) clear any old attributes from map
    // b) repopulate map
    var attributeMap = this.getAttributeMap();
    for (attribName in attributeMap) {
        delete attributeMap[attribName];
    }


    var attributeArray = myCookieVal.split(this.ATTRIBUTE_DELIM);
    var attribCount = attributeArray.length;
    for (var i=0; i<attribCount; i++) {
        var nameValPair = attributeArray[i].split(this.NAME_VALUE_DELIM );
        attributeMap[nameValPair[0]] = decodeURIComponent(nameValPair[1]); //item and index 0 := attributeName; index 1 := attribute value
        //alert( "attributeName := " + nameValPair[0] + "; attributeValue := " + attributeMap[nameValPair[0]]);
    }
    return true;
}

// -----------------------------------------------------------------------------
// Sets the expiration date on this cookie so that the next time it saved to
// the document's cookie it will be removed. For example, if you want to remove
// a cookie named "mode", you could use script like the following:
//
//   var cookieToRmv = new WRSCookie(document, "mode");
//   cookieToRmv.markForRemoval;
//   WRSCookie.saveToDocument(cookieToRmv);
// -----------------------------------------------------------------------------
WRSCookie.prototype.removeFromDocument = function()
{   //set expiration date to Date we know has passed
    this.expiration = new Date( Date.UTC(1970, 1, 1, 0, 0, 0, 0) );
    this.saveToDocument();
}

WRSCookie.prototype.updateExpirationInYears = function(yearsInFuture)
{
    var now = new Date();
    var yearFromTodayInMs = Date.UTC(now.getUTCFullYear()+yearsInFuture, 1, 1, 0, 0, 0, 0);
    this.expiration = new Date(yearFromTodayInMs);
}

WRSCookie.prototype.extractCookieDefn = function(docCookie)
{
    var retval = null;
    var start = docCookie.indexOf(this.name + "=");
    if (start == -1) {
        return retval;
    }
    var end = docCookie.indexOf(";", start);
    if (end == -1) {
        end = docCookie.length;
    }
    retval = docCookie.substring(start, end);
    return retval;
}

// -----------------------------------------------------------------------------
// Static method that saves the supplie WRSCookie object to the document with
// which the cookies is associated. The values of all other cookies in the
// document's cookie property are preserved. That is the values of all cookies
// whose name is not that of the supplied WRSCookie.
//
// @param wrsCookie - The WRSCookie whose value and attributes are to be saved
//                    to its Document. Required.
// -----------------------------------------------------------------------------
WRSCookie.prototype.saveToDocument = function ()
{
    this.store(); //update cookie value with all attributes
    this.document.cookie = this.value;

    //alert( "document.cookie := " + this.document.cookie);
}

