////////////////////////////////////////////////////////
// EdmundsCookieLife 
////////////////////////////////////////////////////////
var EdmundsCookieLife = Class.create();
EdmundsCookieLife.prototype = {

    initialize: function(cookieName, timeToLiveSeconds) {
        this.cookieName = cookieName;
        this.timeToLiveSeconds = timeToLiveSeconds;
    },

    getTimeToLive: function() {
        return this.timeToLiveSeconds;
    },

    getCookieName: function() {
        return this.cookieName;
    }

};

////////////////////////////////////////////////////////
// UserTrack
////////////////////////////////////////////////////////
var UserTrack = Class.create();
UserTrack.prototype = {


    initialize: function() {
        this.edmunds_domain = ".edmunds.com";
        this.root_path = "/";
        this.edmunds_cookie_name = "edmunds";
        this.zip_cookie_name = "zip";
        this.edw_cookie_name = "edw";
        this.apache_cookie_name = "Apache";
        this.edw_timestamp_cookie_name = "edwtimestamp";
        this.state_cookie_name = "state";
        this.countyfips_cookie_name = "countyfips";
        this.session = new EdmundsCookieLife("EdmundsSession", -1);
        this.oneYear = new EdmundsCookieLife("EdmundsYear", 60*60*24*365);
        this.thirtyMinute = new EdmundsCookieLife("EdmundsThirtyMinute", 60*30);  
        // Combined cookie delimiter.  See UserTrack.  Single char.
        this.DELIM = "&";
    },

  setStateCountyInfo: function(t) {
    var stateTags = t.responseXML.getElementsByTagName("state");
    if(stateTags && stateTags[0] && stateTags[0].childNodes[0]) {
      this.setCookieValue(this.state_cookie_name, stateTags[0].childNodes[0].nodeValue, this.oneYear);
    }
    var countyTags = t.responseXML.getElementsByTagName("county-fips");
    if(countyTags && countyTags[0] && countyTags[0].childNodes[0]) {
      this.setCookieValue(this.countyfips_cookie_name, countyTags[0].childNodes[0].nodeValue, this.oneYear);
    }
    this.doneFlag = true;
  },
  displayError: function(t, e) {
    this.doneFlag = true;
  },
  queryStateCountyInfo: function(zipcode) {
    var opt = {
      method:'get',
      asynchronous:false,
      parameters:'zipcode=' + zipcode,
      onSuccess: this.setStateCountyInfo.bind(this),
      on404: this.displayError.bind(this),
      onFailure: this.displayError.bind(this),
      onException: this.displayError.bind(this)
    }
    this.doneFlag = false;
    new Ajax.Request("/zipcode/queryZIP.jsp", opt);
  },

    // Retrieve the individual edmunds cookie value.
    // This is either the cookie named "edmunds" or the "Apache" cookie.
    getEdmundsCookie: function() {
            var edmundsCookie = this.getCookieValue(this.edmunds_cookie_name, true);
            if (edmundsCookie == null || edmundsCookie == "") {
                return this.getCookieValue(this.apache_cookie_name, true);
            } else {
                return edmundsCookie;
            }
    }, 

    // Retrieve the edw cookie value.
    getEdwCookie: function() {
            return this.getCookieValue(this.edw_cookie_name, true);
    },

    // Retrieve the zip cookie value from the EdmundsYear combined cookie.
    // If no zip cookie value, return an empty string.
    getZipCookie: function() {
            var retval = this.getCookieValue(this.zip_cookie_name, false);
            if (retval == null) {
                return "";
            }
            return retval;
    },

    // Set the zip cookie value in the EdmundsYear combined cookie.
    setZipCookie: function(zip) {
        this.queryStateCountyInfo(zip);
        return(this.setCookieValue(this.zip_cookie_name, zip, this.oneYear));       
    },

    // getCookieValue(string, boolean)
    // Retrieve a cookie value
    //  From a individual named cookie (eg: edmunds, edw)
    // or if not separate cookie
    //  From the EdmundsSession combined cookie
    // or
    //  From the EdmundsYear combined cookie
    // Returns a cookie value or null if no such cookie exists.
    getCookieValue: function(cookieName, storeSeparate) {
        var dc = document.cookie;
        
        if (dc == null || dc.length == 0) {
            return null;
        }
        
        if (storeSeparate) {
            return(this.getCookie(cookieName));
        } else {

            var edmundsSessionData = this.getCookieValue(this.session.getCookieName(), true);
            if (edmundsSessionData != null) {
                var cookieData = this.getEdmundsData(cookieName, edmundsSessionData);
                if (cookieData != null) {
                    return(unescape(cookieData));
                }
                // Do not return null here.  We must check year cookie.
            }

            var edmundsYearData = this.getCookieValue(this.oneYear.getCookieName(), true);
            if (edmundsYearData != null) {
                var cookieData = this.getEdmundsData(cookieName, edmundsYearData);
                if (cookieData != null) {
                    return(unescape(cookieData));
                }
            }
        }

        return null;
    },

    // setCookieValue(string, string, EdmundsCookieLife Object, boolean)
    // Set a cookie as a separate (if storeSeparate == true)
    // Or as part of the combined cookie cookieLife.
    setCookieValue: function(cookieName, val, cookieLife, storeSeparate) {
                if (!val || val == '' || val == 'null') {
                    return;
                }
        if (storeSeparate) {
                // Store as an individual cookie.
            var expdate = new Date();
            if (cookieLife && cookieLife.getTimeToLive() == -1) {
                // session cookies have no expire date.
                expdate = false;
            } else {
                // Add TTL (milliseconds) to current time.
                var exptime = expdate.getTime();
                exptime += cookieLife.getTimeToLive()*1000;
                expdate.setTime(exptime);           
            }
            return(this.setCookie(cookieName, val, expdate, this.root_path, this.edmunds_domain));

        } else {
            // Store in the "cookieLife" (session or year) combined cookie.

            // Get the value of the combined cookie.
            // Delimiters will be decoded, but the individual values still encoded.
            var combinedData = this.getCookieValue(cookieLife.getCookieName(), true);
            var new_combinedData = "";

            // Escape any curious characters (space, |, etc).
            // We will match this with unescape in getCookieValue().
            val = escape(val);

            if (combinedData == null) {
                // This is the first value in the combined cookie
                // A leading delimiter makes searching easy later.
                new_combinedData = this.DELIM + cookieName + "=" + val;
            } else {
                // Try to find the cookieName in the combined cookie (eg: "&sq_data=10002,10003&...")
                var begin = combinedData.indexOf(this.DELIM + cookieName + "=");
                if (begin != -1) {
                    // Use Regular Expressions on new browsers, substring on old ones.
                    if (RegExp) {
                        var oldvalue = new RegExp(cookieName + "=[^" + this.DELIM + "]*");
                        var newvalue = cookieName + "=" + val;
                        new_combinedData = combinedData.replace(oldvalue, newvalue);
                    } else {
                        // Backwards compatibility for old browsers that might
                        // not support Regular Expressions.
                        var end = combinedData.indexOf(this.DELIM, begin + 1);
                        new_combinedData = this.DELIM + cookieName + "=" + val;
                        if (begin == 0 && end == -1) {
                            // we replace the whole cookie.
                        } else if (begin == 0) {
                            // replaced cookie was at the beginning of the string.
                            new_combinedData += combinedData.substring(end);
                        } else if (end == -1) {
                            // replaced cookie was at the end of the string.
                            new_combinedData += combinedData.substring(0, begin);
                        } else {
                            // replace cookie was in middle of the string.
                            new_combinedData += combinedData.substring(0, begin);
                            new_combinedData += combinedData.substring(end);
                        }
                    }                   
                } else {
                    // Cookie is not in the combined string, so just append it.
                    new_combinedData = combinedData + this.DELIM + cookieName + "=" + val;
                }
        
            }
            // Recurse this routine to update the combined cookie.
            // Note the storeSeparate parameter is "true", storing the combined cookie.
            return(this.setCookieValue(cookieLife.getCookieName(), new_combinedData, cookieLife, true));  

        }    
    },

    // getEdmundsData(string, string)
    // combinedData is the delimited string from one of the combined cookies (year or session).
    // Finds the specified name and returns the associated value.
    // Returns null if the name does not exist.
    getEdmundsData: function(cookieName, combinedData) {
        var prefix = cookieName + "=";
        var begin = combinedData.indexOf(this.DELIM + prefix);
        if (begin == -1) {
            return null;
        } else {
            begin++;  // skip past the delimiter. (XXX this.DELIM.length)
        }

        var end = combinedData.indexOf(this.DELIM, begin);
        if (end == -1) { end = combinedData.length; }
        return(combinedData.substring(begin + prefix.length, end));

    },

    // getCookie(string)
    // Get an individual cookie from the browser.
    // Cookies are delimited by "; " (eg: "edw=101; edmunds=500b; zip=06226")
    // Returns null if cookie does not exist.
    // Otherwise returns the value from cookie string ("06226" from "zip=06226")
    getCookie: function(name) {
        var dc = "; " + document.cookie;
        var prefix = name + "=";
        var begin = dc.indexOf("; " + prefix);
        if (begin == -1) {
            return null;
        } else {
            begin += 2;  // skip past the delimiter.
        }

        // Find the end of this cookie value.
        var end = dc.indexOf(";", begin);
        // If the last cookie, grab through the end of the string.
        if (end == -1) { end = dc.length; }
        return(dc.substring(begin + prefix.length, end));
    },

    // setCookie(string, string, DATE, string, string, boolean)
    // Set an individual cookie in the browser.
    // expires must be a date object.
    // (Can this ever return false?)
    setCookie: function(name, value, expires, path, domain, secure) {
        var cookie_str = escape(name) + "=" + value +
        ((expires) ? "; expires=" + expires.toGMTString() : "") +
        ((path) ? "; path=" + path : "") +
        ((domain) ? "; domain=" + domain : "") +
        ((secure) ? "; secure" : "");       
        //alert("Setting: " + cookie_str);
        return(document.cookie = cookie_str);
    },


    // get a timestamp to help tie pageview and ad data (edw and dart snap logs)
    getEdwTimestamp: function() {
        return window.timestamp || new Date().getTime();
    },

    // set a timestamp to help tie pageview and ad data (edw and dart snap logs)
    setEdwTimestamp: function(ts) {
        timestamp = ts;
    },
    
    // Retrieve the timestamp cookie value.
    getEdwTimestampCookie: function() {
        return this.getCookieValue(this.edw_timestamp_cookie_name, true);
    },
    
    
    // Migrate old cookies into new combined cookie locations.
    migrateCookies: function() {
        var expiredate = new Date(1);

        // check for broken edmunds cookie
        var edmundsCookie = this.getCookie("edmunds");
        if (edmundsCookie && (edmundsCookie == 'null' || edmundsCookie == '')) {
          this.setCookie("edmunds", "", expiredate, this.root_path, this.edmunds_domain);    
        }

        var zip = this.getCookie("zip");
        if (zip) {
            this.setZipCookie(zip);
            this.setCookie("zip", "", expiredate, this.root_path, this.edmunds_domain);
        }
        // check delete zip @ www.edmunds.com?  how common?

        // AL is handled by DCMCommon
        // FN, LN, CID, EMAIL, THSN, THA, ET, savedcar
        var old_cookies = new Array("FN", "LN", "CID", "EMAIL", "THSN", "THA", "ET", "savedcar");
        for (var i = 0; i < old_cookies.length; i++) {
            var name = old_cookies[i];
            var val = this.getCookie(name);
            //alert("Cookie " + name + " = " + val);
            if (val) {
                this.setCookieValue(name, val, this.session);
                this.setCookie(name, "", expiredate, this.root_path, this.edmunds_domain);
            }
        }
    }
    

};

/////////////////////////////////////////////////////////

EdmundsCookieLife.Session = new EdmundsCookieLife("EdmundsSession", -1);
EdmundsCookieLife.OneYear = new EdmundsCookieLife("EdmundsYear", 60*60*24*365);
EdmundsCookieLife.ThirtyMinute = new EdmundsCookieLife("EdmundsThirtyMinute", 60*30);
var userTrack = new UserTrack();
userTrack.migrateCookies();
var timestamp;

