/**
 * Root object/namespace of the tracking API.
 * <p/>
 * @namespace
 * @author <a href="mailto:info@winformation.de">winformation</a>
 * 
 *
 * This Script uses parts of Math.uuid.js (v1.4) under MIT licence
 * 
 * Copyright (c) 2010 Robert Kieffer
 *
 * Dual licensed under the MIT and GPL licenses.
 *     
 */
 
 /**
 * Begin  of part Math.uuid.js (v1.4) under MIT licence, Copyright (c) 2010 Robert Kieffer     
 *     
 */
 
(function() {
  // Private array of chars to use
  var CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''); 


  // A more performant, but slightly bulkier, RFC4122v4 solution.  We boost performance
  // by minimizing calls to random()
  Math.uuid = function() {
    var chars = CHARS, uuid = new Array(36), rnd=0, r;
    for (var i = 0; i < 36; i++) {
      if (i==8 || i==13 ||  i==18 || i==23) {
        uuid[i] = '-';
      } else if (i==14) {
        uuid[i] = '4';
      } else {
        if (rnd <= 0x02) rnd = 0x2000000 + (Math.random()*0x1000000)|0;
        r = rnd & 0xf;
        rnd = rnd >> 4;
        uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
      }
    }
    return uuid.join('');
  };

})(); 

/**
 * End of part Math.uuid.js (v1.4)
 *     
 */
 
var TravelAudienceTrack = TravelAudienceTrack || {
    /**
     * Tracker configuration.
     * @namespace
     */
    config: {
        /**
         * URL of the tracker.
         * @type String
         */
        baseUrl: 'http://data.traveltainment.de/app_1/tracker/track1.js',
        /**
         * How long the global cookies shall live (in milliseconds).
         * @type Number
         * @default 100000000000
         */
        cookieLifetime: 100000000000,
        /**
         * Cookie domain.
         * <p/>
         * If empty, the cookie domain is equal to the domain in URL.
         * @type String
         * @default: <code>null</code>
         */
        cookieDomain: null,
        /**
         * Cookie path.
         * <p/>
         * If empty, <code>/</code> is assumed as a path.
         * @type String
         * @default: <code>null</code>
         */
        cookiePath: null,
        /**
         * Cookie name.
         * <p/>
         * The name of the cookie that will store global tracking parameters.
         * @default <code>'_tracker'</code>.
         * @type String
         */
        cookieName: '_ttTracker',
        /**
         * Name of the parameter for cross-site cookie transfer.
         * @default <code>'_trackingCookie'</code>.
         * @see TravelAudienceTrack.global.buildCrossSiteUrl
         * @type String
         */
        crossSiteParam: '_ttTrackerCookie'
    },
   /**
     * Tracker settings.
     * Contains browserdetection, special options etc      
     * @namespace
     */
    
    settings: {
    
          /**
           * Use images instead of script
           * @default <code>'false'</code>.
           * @type booelaen
           */
          useImageApproach: false,
          /**
           * Fix for IE6-7 http://support.microsoft.com/kb/927917/en-us
           * Adds a additional child.
           * Overwritten if autodetect is true                      
           * @default <code>'false'</code>.
           * @type booelaen
           */
          nestedFix: false,
            
          /**
           * Detects Browser and sets settings                    
           * @default <code>'true'</code>.
           * @type booelaen
           */  
          autodetect: true
    
    },
     _anchorDiv: null,

    /**
     * Global parameters storage.
     *
     * <p>Used to manage parameters that shall be submitted implicitly with every tracking request for the current site.</p>
     * <p>
     * Technically, global parameters are stored in a cookie bound to the domain of the site where this script is loaded from.
     * Global parameters are represented as a single key/value object which is serialized to a string using the JSON notation which is URL-encoded.
     * The same format is used to pass global parameters for cross-site transfers.
     * </p>
     *
     * @namespace
     */
    global: {
        _data: {},

        /**
         * Set a global parameter.
         *
         * @function
         * @param key parameter key, can be string to set one variable, or object {key1: value1, key2: value2, ...} to set multiple variables
         * @param value parameter value; use <code>null</code> to remove the parameter from the global storage.
         * @example Tracking.global.set('siteId', 12);
         */
        set: function(key, value) {
            if (typeof key == 'string') {
                var tmpKey = {};
                tmpKey[key] = value;
                key = tmpKey;
            }
            for (var k in key) {
                if (key.hasOwnProperty(k)) {
                    if (key[k]) {
                        this._data[k] = key[k];
                    } else {
                        if (this._data[k]) {
                            delete this._data[k];
                        }
                    }
                }
            }
            this._toCookies();
        },
        
        /**
         * Get a global parameter.
         * @param key parameter key
         * @return global parameter value or <code>null</code>.
         * @example
         * var siteId = Tracking.global.get('siteId');
         */
        get: function(key) {
            return this._data[key];
        },

        /**
         * Get all global parameters.
         * @return a JavaScript object with key/value representation of global parameters.
         * @example
         * for (var key in TravelAudienceTrack.global.getAll()) {
         *      alert(TravelAudienceTrack.global.get(key));
         * }
         *
         */
        getAll: function() {
            return this._data;
        },

        /**
         * Clear all global parameters.
         */
        clear: function() {
            this._data = {};
            this._toCookies();
        },

        _toCookies: function() {
            try {
                this._setCookie(TravelAudienceTrack.config.cookieName, this._serialize(this._data));
            } catch(e) {
            }
        },

        _fromCookies: function() {
            try {
                this._data = this._deserialize(this._getCookie(TravelAudienceTrack.config.cookieName));
                if (!this._data) {
                    this._data = {};
                    this._data['UUID'] = Math.uuid();
                } else if  (!this._data['UUID']) {
                    this._data['UUID'] = Math.uuid();
                }
                
            } catch(e) {
            }
        },

        _setCookie: function (name, value) {
            if (TravelAudienceTrack.config.cookieLifetime) {
                var date = new Date();
                date.setTime(date.getTime() + TravelAudienceTrack.config.cookieLifetime);
            }

            document.cookie = name + "=" + escape(value) +
                              (date ? "; expires=" + date.toGMTString() : "") +
                              ((TravelAudienceTrack.config.cookiePath) ? "; path=" + TravelAudienceTrack.config.cookiePath : "") +
                              ((TravelAudienceTrack.config.cookieDomain) ? "; domain=" + TravelAudienceTrack.config.cookieDomain : "");
        },

        _getCookie: function (name) {
            var nameEQ = name + "=";
            var ca = document.cookie.split(';');
            var c;
            for (var i = 0; i < ca.length; i++) {
                c = ca[i];
                while (c.charAt(0) == ' ') c = c.substring(1, c.length);
                if (c.indexOf(nameEQ) == 0) return unescape(c.substring(nameEQ.length, c.length));
            }
            return '';
        },

        _clearCookie: function (name) {
            document.cookie = name + "=; expires=" + (new Date().toGMTString() - 1000) +
                              ((TravelAudienceTrack.config.cookiePath) ? "; path=" + TravelAudienceTrack.config.cookiePath : "") +
                              ((TravelAudienceTrack.config.cookieDomain) ? "; domain=" + TravelAudienceTrack.config.cookieDomain : "");

        },

        _serialize : function (obj) {
            var t = typeof (obj);
            if (t != "object" || obj === null) {
                if (t == "string") obj = '"' + obj + '"';
                return String(obj);
            }
            else {
                var n, v, json = [], arr = (obj && obj.constructor == Array);
                for (n in obj) {
                    v = obj[n];
                    t = typeof(v);
                    if (t == "string") v = '"' + v + '"';
                    else if (t == "object" && v !== null) v = this._serialize(v);
                    json.push((arr ? "" : '"' + n + '":') + String(v));
                }
                return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
            }
        },

        _deserialize: function(str) {
            if (str === "") {
                str = '""';
            }
            eval("var p=" + str + ";");
            return p;
        },

        _buildXSCode: function() {
            var data = {};
            data[TravelAudienceTrack.config.crossSiteParam] = this._serialize(this._data);
            return TravelAudienceTrack._dataToQueryString(data);
        },

        _handleXSParameter: function() {
            var url = window.location.href;
            var paramPiece = '#' + TravelAudienceTrack.config.crossSiteParam + '=';
            var index = url.indexOf(paramPiece);
            var param;
            if (index >= 0) {
                param = decodeURIComponent(url.substr(index + paramPiece.length).split('#')[0]);
                try {
                    this._data = this._deserialize(param);
                    if (!this._data) {
                        this._data = {};
                    }
                } catch(e) {
                }
                this._toCookies();
            }
        },

        /**
         * Build a cross-site URL.
         * <p/>
         * In some cases it may be required to transfer global parameters to a site in a different domain.
         * This method changes the given URL by appending some technical parameters as a URL anchor (<code>#</code>).
         * A tracking script on the target site should then transparently populate its global parameters with the global parameters of the source site.
         * @function
         * @param {String} url URL to be modified.
         * @type String
         * @example
         * document.write('&lt;a href="' + TravelAudienceTrack.global.buildCrossSiteUrl('http://some.site.com/') + '"&gt;');
         */
        buildCrossSiteUrl: function(url) {
            return url + '#' + this._buildXSCode();
        }
    },

    _dataToQueryString: function(data) {
        var str = '';
        for (key in data) {
            if (str) {
                str += '&';
            }
            str += encodeURIComponent(key) + '=' + encodeURIComponent(data[key]);
        }
        return str;
    },

    _buildDataUrl: function(url, data) {
        if (data) {
            if (url.indexOf('?') === -1) {
                url += '?';
            } else {
                url += '&';
            }

            url += this._dataToQueryString(data) + "&__trackerRequestId=" + Math.random();
        }
        return url;
    },

    _sendData: function(url, data, callback) {
    
         var dataUrl = TravelAudienceTrack._buildDataUrl(url, data);
         
        if (TravelAudienceTrack.settings.useImageApproach) {
            var image = new Image();
            image.src = dataUrl;
        } else {
         var script = document.createElement('script');
         script.setAttribute('src', dataUrl);
         if (typeof callback == 'function') {
             this.sendCallback = callback;
             // Fallback - nach 250ms wird in jedem Fall die callback-Funktion aufgerufen, auch wenn onload fehlschlägt
             window.setTimeout('TravelAudienceTrack.sendCallback()', 500);
             script.setAttribute('onload', 'TravelAudienceTrack.sendCallback()');
         }
         script.setAttribute('type', 'text/javascript');
         if (!TravelAudienceTrack.settings.nestedFix) {
           document.body.appendChild(script);
         } else {
           if (_anchorDiv == null) {
               _anchorDiv = document.getElementById('TravelAudienceAnchor');
           }
           if (_anchorDiv != null) {
               _anchorDiv.appendChild(script);
           }
         }
        }
        
    },
    
    
   _getIEVersion:  function () {

    var rv = -1; // Return value assumes failure.

    if (navigator.appName == 'Microsoft Internet Explorer') {

        var ua = navigator.userAgent;

        var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");

        if (re.exec(ua) != null)

            rv = parseFloat(RegExp.$1);

    }

    return rv;

  }, 

    /**
     * Submit the tracking data.
     * @param {Object} data tracking data in the form of JavaScript key/value object.
     * @param {Boolean} [skipGlobals=false] whether global parameters should be skipped. By default, all global parameters are sent along with tracking data.
     * @example
     * TravelAudienceTrack.send({
     *     a: 1,
     *     b: "lorem ipsum"
     * });
     */
    send: function(data, callback, skipGlobals) {
        var _data = skipGlobals ? {} : this._clone(this.global._data);
        this._copy(_data, data);
        this._sendData(this.config.baseUrl, _data, callback);
    },
    
    sendCallback: function() {
    },

    _clone: function(src) {
        if (src == null || typeof(src) != 'object')
            return src;

        var dst = src.constructor();
        this._copy(dst, src);

        return dst;
    },

    _copy: function(dst, src) {
        if (src == null || typeof(src) != 'object') {
            dst = src;
            return dst;
        }

        for (var key in src)
            dst[key] = this._clone(src[key]);
        return dst;
    },

    _init: function() {
        if (this._initialized) {
            return;
        }
    
        if (TravelAudienceTrack.settings.autodetect) {
             var v=this._getIEVersion();
             if  ( (v>5.5) && (v<=7.0) )   {
                TravelAudienceTrack.settings.nestedFix = true;
             }
        
        }
    
        if (TravelAudienceTrack.settings.nestedFix) {
        
          //_anchorDiv = document.createElement('div');
          //_anchorDiv.setAttribute('id','TravelAudienceAnchor');
          //document.body.appendchild(_anchorDiv);
          
          document.write('<div id="TravelAudienceAnchor" style="visible:false;"></div>');
          _anchorDiv = document.getElementById('TravelAudienceAnchor');
          
        }
        
        this._initialized = true;
        this.global._fromCookies();
        this.global._handleXSParameter();
        this.processQueue();
    },

    /**
     * Submit series of events stored in the queue.
     *
     * This method may be useful for registering events without certainty that the TravelAudienceTrack object is initialized.
     *
     * @param {Array} [queue] queue containing events to send; if omitted,
     * the global variable <code>_trackerEventQueue</code> is assumed.
     *
     * @example
     * // create the event queue or use the existing one
     * var _trackerEventQueue = _trackerEventQueue || [];
     * // queue event
     * _trackerEventQueue.push({event: 'initialized'});
     * // if the tracker object is already initialized then submit all events in the queue,
     * // otherwise the tracker will automatically process the queue on initialization
     * if (window.TravelAudienceTrack)
     *     TravelAudienceTrack.processQueue();
     */
    processQueue: function(queue) {
        var _queue = queue || window._trackerEventQueue;
        if(_queue) {
            try {
                while (_queue.length > 0) {
                    this.send(_queue.shift());
                }
            } catch(e) {
            }
        }
    }

};

TravelAudienceTrack._init();

