/* See ./tracking-service-doc.js for documented version of this file */

document.write('<script type="text/javascript">');
document.write('wa = new Object'); // DTO populated later on, by wrapper JS, and consumed by vendor's JS.
document.write('</script>');
document.write('<script type="text/javascript" src="/ConsolidatedLogin/js/evolytics_s_code.js"></script>');

var AccountInfoBean = 
{
    accountId  : null,
    
    debug      : false,
    
    init : function()
    {
        return this;
    }
}

var UserInfoBean = 
{
   country        : null,
   contracts      : null,
   contractType   : null,
   guid           : null,
   language       : null,

   init : function()
   {
       return this;
   }
}

var PageInfoBean = 
{
   localizedName   : null,
   logicalName     : null,
   siteSection     : null,
   loginMessage    : null,
   errorMessage    : null,
   
   init : function()
   {
       return this;
   }
}

var CampaignInfoBean = 
{
   name       : null,
   source     : null,
   medium     : null,
   content    : null,
   term       : null,

   init : function()
   {
       return this;
   }
}


var TrackingServiceBean = 
{
   accountInfo : null,
   campaignInfo : null,
   pageInfo : null,
   userInfo : null,
   

   init : function()
   {
	this.accountInfo = new AccountInfoBean.init();
	this.campaignInfo = new CampaignInfoBean.init();
	this.pageInfo = new PageInfoBean.init();
	this.userInfo = new UserInfoBean.init();
	return this;
   },

   merge : function(trackingSvcBeanSrc, trackingSvcBeanTarget)
   {
		for (var key in trackingSvcBeanSrc) {
			if (trackingSvcBeanSrc.hasOwnProperty(key)) {
				var childInfoBean = trackingSvcBeanSrc[key];
				for (var subkey in childInfoBean) {
					if (childInfoBean.hasOwnProperty(subkey)) {
						trackingSvcBeanTarget[key][subkey] = childInfoBean[subkey];
					}
				}
			}					
		}
   }
}

var Reporter = 
{
   synchronizeWithTrackingCookie : function(trackingSvcBean, debug) {
       var trackingSvcBeanFromCookie = TrackingServiceCookie.getTrackingSvcBean();
       this.debug(trackingSvcBean, trackingSvcBeanFromCookie, debug);
       
       if (trackingSvcBeanFromCookie)
       {
    	   TrackingServiceBean.merge(trackingSvcBean, trackingSvcBeanFromCookie);
           TrackingServiceCookie.persistTrackingSvcBean(trackingSvcBeanFromCookie);
           return trackingSvcBeanFromCookie;
       } else {
           TrackingServiceCookie.persistTrackingSvcBean(trackingSvcBean);
           return trackingSvcBean;
       }
   },
   
   
   

   debug : function(trackingSvcBean, trackingSvcBeanFromCookie, debug) {

	   var query = window.location.search.substring(1);
		var vars = query.split("&");
		for (var i=0;i<vars.length;i++) {
			var pair = vars[i].split("=");
			if (pair[0] == "debug-tracking-service" && pair[1]) {
				debug = true;
			}
		}

		if (trackingSvcBeanFromCookie && trackingSvcBeanFromCookie.accountInfo.debug)
		{
			debug = true;
		}
		
		if (debug)
		{
			trackingSvcBean.accountInfo.debug = true;
			alert("Tracking data currently persisted in cookie: " + JSON.stringify(trackingSvcBeanFromCookie));
			alert("Tracking data provided by this page request: " + JSON.stringify(trackingSvcBean));
		}
   },
   
   isDebugEnabled : function(trackingSvcBean) {
	   if (trackingSvcBean.accountInfo.debug)
	   {
		   return true;
	   }
	   
	   else
	   {
		   return false;
	   }
   },
   
   
   
   
   
   copyTrackingProperties : function(trackingSvcBean) {
		wa.accountList			=	trackingSvcBean.accountInfo.accountId; // Example: "autodesk-dev1"

		// UserInfo:
		wa.profileLanguage		=	trackingSvcBean.userInfo.language; // Example: "enu" 
		wa.profileCountry		=	trackingSvcBean.userInfo.country; // Example: "us"
		wa.guid					=	trackingSvcBean.userInfo.guid; // Example: "200703030012189"
		wa.contractNums			=	trackingSvcBean.userInfo.contracts; // Example: "1234567,7766357"
		wa.productTypes			=	trackingSvcBean.userInfo.contractType; // Example: "Subscription Gold, Subscription Platinum" 

		// PageInfo:
		wa.pageNameTitle		=	trackingSvcBean.pageInfo.localizedName; // Example: "Éditez le profil"; 
		wa.pageNameStandard		=	trackingSvcBean.pageInfo.logicalName; // Example: "Edit Profile"; 
		wa.pathMain				=	trackingSvcBean.pageInfo.siteSection; // Example: "Legacy Subscription Center"; 
		wa.loginMessage			=	trackingSvcBean.pageInfo.loginMessage; // Example: "Login Successful";
		wa.errorMessage			=	trackingSvcBean.pageInfo.errorMessage; // Example: "Expired contract";

   },
   
   report : function(trackingSvcBean, debug) {
		trackingSvcBean = this.synchronizeWithTrackingCookie(trackingSvcBean, debug);

		if (this.isDebugEnabled(trackingSvcBean))
		{
			alert("Tracking data to be reported: " + JSON.stringify(trackingSvcBean));
		}

		this.copyTrackingProperties(trackingSvcBean);
		var vendorSvc=s.t(); // "s.t()" is defined in vendor-specific-tracking-service.js
		
		if(vendorSvc) {
			document.write(vendorSvc); // submits data
		}
		
   }

}


var TrackingServiceCookie = 
{
		_name     : "subportal-tracking-service",
		_expires  : null,
		_path     : "/",
		_domain   : "autodesk.com", // cookie must be accessible across all Subportal properties
		_secure   : false,

		persistTrackingSvcBean : function(trackingSvcBean)
		{
			if (this.isUpdateRequired(trackingSvcBean))
			{
				var serializedBean = JSON.stringify(trackingSvcBean);
				var encodedSerializedBean = Base64.encode(serializedBean);
				document.cookie = 
					this._name + "="+ escape(encodedSerializedBean) +
	                ((this._expires) ? "; expires=" + _this._expires : "") +
	                "; path="       + this._path +
	                "; domain="     + this._domain +
	                ((this._secure) ? "; secure" : "")
	                ;
			}
		},

		getTrackingSvcBean : function()
		{
			 var dc = document.cookie;
			 var prefix = this._name + "=";
			 var begin = dc.indexOf("; " + prefix);
			 if (begin == -1) {
			   begin = dc.indexOf(prefix);
			   if (begin != 0) return null;
			 } else
			   begin += 2;
			 var end = document.cookie.indexOf(";", begin);
			 if (end == -1)
			   end = dc.length;
			 var encodedSerializedBean = unescape(dc.substring(begin + prefix.length, end));
			 var serializedBean = Base64.decode(encodedSerializedBean);
			 var trackingSvcBean = JSON.parse(serializedBean);
			 return trackingSvcBean;
		},

		// returns true if there is a difference between the existing cookie, and the new data
		isUpdateRequired : function(trackingSvcBean)
		{
			var updateCookie = false;
			
			// only update cookie if it has changed. Detect the change:
			var existingBean = this.getTrackingSvcBean();
			
			if (existingBean)
			{
				if (JSON.stringify(existingBean) != JSON.stringify(trackingSvcBean))
				{
					updateCookie = true;
				}				
			} else {
				updateCookie = true;
			}
			
			return updateCookie;
		}
}

 
var Base64 = 
{
 
    // private property
    _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
 
    // public method for encoding
    encode : function (input) {
        var output = "";
        var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
        var i = 0;
 
        input = Base64._utf8_encode(input);
 
        while (i < input.length) {
 
            chr1 = input.charCodeAt(i++);
            chr2 = input.charCodeAt(i++);
            chr3 = input.charCodeAt(i++);
 
            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;
 
            if (isNaN(chr2)) {
                enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
                enc4 = 64;
            }
 
            output = output +
            this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
            this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
 
        }
 
        return output;
    },
 
    // public method for decoding
    decode : function (input) {
        var output = "";
        var chr1, chr2, chr3;
        var enc1, enc2, enc3, enc4;
        var i = 0;
 
        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
 
        while (i < input.length) {
 
            enc1 = this._keyStr.indexOf(input.charAt(i++));
            enc2 = this._keyStr.indexOf(input.charAt(i++));
            enc3 = this._keyStr.indexOf(input.charAt(i++));
            enc4 = this._keyStr.indexOf(input.charAt(i++));
 
            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;
 
            output = output + String.fromCharCode(chr1);
 
            if (enc3 != 64) {
                output = output + String.fromCharCode(chr2);
            }
            if (enc4 != 64) {
                output = output + String.fromCharCode(chr3);
            }
 
        }
 
        output = Base64._utf8_decode(output);
 
        return output;
 
    },
 
    // private method for UTF-8 encoding
    _utf8_encode : function (string) {
        string = string.replace(/\r\n/g,"\n");
        var utftext = "";
 
        for (var n = 0; n < string.length; n++) {
 
            var c = string.charCodeAt(n);
 
            if (c < 128) {
                utftext += String.fromCharCode(c);
            }
            else if((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }
 
        }
 
        return utftext;
    },
 
    // private method for UTF-8 decoding
    _utf8_decode : function (utftext) {
        var string = "";
        var i = 0;
        var c = c1 = c2 = 0;
 
        while ( i < utftext.length ) {
 
            c = utftext.charCodeAt(i);
 
            if (c < 128) {
                string += String.fromCharCode(c);
                i++;
            }
            else if((c > 191) && (c < 224)) {
                c2 = utftext.charCodeAt(i+1);
                string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                i += 2;
            }
            else {
                c2 = utftext.charCodeAt(i+1);
                c3 = utftext.charCodeAt(i+2);
                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                i += 3;
            }
 
        }
 
        return string;
    }
}



/*jslint evil: true */

/*global JSON */

/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
lastIndex, length, parse, prototype, push, replace, slice, stringify,
test, toJSON, toString, valueOf
*/

//Create a JSON object only if one does not already exist. We create the
//methods in a closure to avoid creating global variables.

if (!this.JSON) {
JSON = {};
}
(function () {

function f(n) {
    // Format integers to have at least two digits.
    return n < 10 ? '0' + n : n;
}

if (typeof Date.prototype.toJSON !== 'function') {

    Date.prototype.toJSON = function (key) {

        return this.getUTCFullYear()   + '-' +
             f(this.getUTCMonth() + 1) + '-' +
             f(this.getUTCDate())      + 'T' +
             f(this.getUTCHours())     + ':' +
             f(this.getUTCMinutes())   + ':' +
             f(this.getUTCSeconds())   + 'Z';
    };

    String.prototype.toJSON =
    Number.prototype.toJSON =
    Boolean.prototype.toJSON = function (key) {
        return this.valueOf();
    };
}

var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
    escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
    gap,
    indent,
    meta = {    // table of character substitutions
        '\b': '\\b',
        '\t': '\\t',
        '\n': '\\n',
        '\f': '\\f',
        '\r': '\\r',
        '"' : '\\"',
        '\\': '\\\\'
    },
    rep;


function quote(string) {

    escapable.lastIndex = 0;
    return escapable.test(string) ?
        '"' + string.replace(escapable, function (a) {
            var c = meta[a];
            return typeof c === 'string' ? c :
                '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
        }) + '"' :
        '"' + string + '"';
}


function str(key, holder) {

//Produce a string from holder[key].

    var i,          // The loop counter.
        k,          // The member key.
        v,          // The member value.
        length,
        mind = gap,
        partial,
        value = holder[key];

//If the value has a toJSON method, call it to obtain a replacement value.

    if (value && typeof value === 'object' &&
            typeof value.toJSON === 'function') {
        value = value.toJSON(key);
    }

//If we were called with a replacer function, then call the replacer to
//obtain a replacement value.

    if (typeof rep === 'function') {
        value = rep.call(holder, key, value);
    }

//What happens next depends on the value's type.

    switch (typeof value) {
    case 'string':
        return quote(value);

    case 'number':

//JSON numbers must be finite. Encode non-finite numbers as null.

        return isFinite(value) ? String(value) : 'null';

    case 'boolean':
    case 'null':

        return String(value);

    case 'object':

        if (!value) {
            return 'null';
        }

//Make an array to hold the partial results of stringifying this object value.

        gap += indent;
        partial = [];

//Is the value an array?

        if (Object.prototype.toString.apply(value) === '[object Array]') {

//The value is an array. Stringify every element. Use null as a placeholder
//for non-JSON values.

            length = value.length;
            for (i = 0; i < length; i += 1) {
                partial[i] = str(i, value) || 'null';
            }

//Join all of the elements together, separated with commas, and wrap them in
//brackets.

            v = partial.length === 0 ? '[]' :
                gap ? '[\n' + gap +
                        partial.join(',\n' + gap) + '\n' +
                            mind + ']' :
                      '[' + partial.join(',') + ']';
            gap = mind;
            return v;
        }

//If the replacer is an array, use it to select the members to be stringified.

        if (rep && typeof rep === 'object') {
            length = rep.length;
            for (i = 0; i < length; i += 1) {
                k = rep[i];
                if (typeof k === 'string') {
                    v = str(k, value);
                    if (v) {
                        partial.push(quote(k) + (gap ? ': ' : ':') + v);
                    }
                }
            }
        } else {

//Otherwise, iterate through all of the keys in the object.

            for (k in value) {
                if (Object.hasOwnProperty.call(value, k)) {
                    v = str(k, value);
                    if (v) {
                        partial.push(quote(k) + (gap ? ': ' : ':') + v);
                    }
                }
            }
        }

//Join all of the member texts together, separated with commas,
//and wrap them in braces.

        v = partial.length === 0 ? '{}' :
            gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
                    mind + '}' : '{' + partial.join(',') + '}';
        gap = mind;
        return v;
    }
}

//If the JSON object does not yet have a stringify method, give it one.

if (typeof JSON.stringify !== 'function') {
    JSON.stringify = function (value, replacer, space) {

        var i;
        gap = '';
        indent = '';

//If the space parameter is a number, make an indent string containing that
//many spaces.

        if (typeof space === 'number') {
            for (i = 0; i < space; i += 1) {
                indent += ' ';
            }

//If the space parameter is a string, it will be used as the indent string.

        } else if (typeof space === 'string') {
            indent = space;
        }

//If there is a replacer, it must be a function or an array.
//Otherwise, throw an error.

        rep = replacer;
        if (replacer && typeof replacer !== 'function' &&
                (typeof replacer !== 'object' ||
                 typeof replacer.length !== 'number')) {
            throw new Error('JSON.stringify');
        }

//Make a fake root object containing our value under the key of ''.
//Return the result of stringifying the value.

        return str('', {'': value});
    };
}


//If the JSON object does not yet have a parse method, give it one.

if (typeof JSON.parse !== 'function') {
    JSON.parse = function (text, reviver) {

//The parse method takes a text and an optional reviver function, and returns
//a JavaScript value if the text is a valid JSON text.

        var j;

        function walk(holder, key) {

//The walk method is used to recursively walk the resulting structure so
//that modifications can be made.

            var k, v, value = holder[key];
            if (value && typeof value === 'object') {
                for (k in value) {
                    if (Object.hasOwnProperty.call(value, k)) {
                        v = walk(value, k);
                        if (v !== undefined) {
                            value[k] = v;
                        } else {
                            delete value[k];
                        }
                    }
                }
            }
            return reviver.call(holder, key, value);
        }


        cx.lastIndex = 0;
        if (cx.test(text)) {
            text = text.replace(cx, function (a) {
                return '\\u' +
                    ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
            });
        }


        if (/^[\],:{}\s]*$/.
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

            j = eval('(' + text + ')');
            return typeof reviver === 'function' ?
                walk({'': j}, '') : j;
        }

//If the text is not JSON parseable, then a SyntaxError is thrown.

        throw new SyntaxError('JSON.parse');
    };
}
}());
