/******************************************************************************
 ** ATLAS TRACKING OBJECT
 *****************************************************************************/
 
Atlas = 
{
    /**************************************************************************
     ** INITIALIZATION METHOD
     *************************************************************************/

    // initialize everything and go
    Go : function( country, project, location, view, unload )
    {
        // reference to document referrer to save bytes below
        var dr = document.referrer;
        
        // set single pair value
        this.m_dataMap.single.project = project;
        
        // set pair values
        this.m_dataMap.pair.country.value  = country;
        this.m_dataMap.pair.location.value = location;
        this.m_dataMap.pair.url.value      = encodeURIComponent( dr );
        this.m_dataMap.pair.domain.value   = this.GetDomain( dr );
        this.m_dataMap.pair.keywords.value = this.GetSearchKeywords( dr );
        this.m_dataMap.pair.search.value   = this.GetSearchResult( dr );   
        this.m_dataMap.pair.source.value   = this.GetQuerystringValue( "source" );
        
        // do a view tracking call?
        if ( view )
        {
            // fire view event
            this.View();
        }
        
        // attach to unload?
        if ( unload )
        {
            // bind to page unload event
            this.BindUnloadEvent();
        }
        
        // attach event handler
        document.attachEvent( "onclick", Atlas.Click );
    },    
    
    /**************************************************************************
     ** SETTER METHODS
     *************************************************************************/

    // country setter
    SetCountry : function( country )
    {
        this.m_dataMap.pair.country.value = country;
    },
    
    // location setter
    SetLocation : function( location )
    {
        this.m_dataMap.pair.location.value = location;
    },  
    
    // language setter
    SetLanguage : function( language )
    {
        this.m_dataMap.pair.language.value = language;
    },  
    
    // set internal time pivot
    SetTimePivot : function( pivot )
    {
        this.m_timePivot = pivot;
    },
    
    /**************************************************************************
     ** GETTER METHODS
     *************************************************************************/
    
    // BETA CODE - capture keyword data from search queries
    GetSearchKeywords : function( i )
    {        
        // loop through all m_searchProviders
        for ( var search in this.m_searchProviders )
        {
            // check for a match
            if ( i.indexOf( this.m_searchProviders[ search ].form ) == 0 )
            {                
                // extract keywords
                return this.GetQuerystringValue( this.m_searchProviders[ search ].key, i ).replace( /[+]/g, "," );
            }
        }
        
        // no major search m_searchProviders found, return empty string
        return "";
    },
    
    // BETA CODE - capture keyword data from search queries
    GetSearchResult : function( i )
    {        
        // loop through all m_searchProviders
        for ( var search in this.m_searchProviders )
        {
            // check for a match
            if ( i.indexOf( this.m_searchProviders[ search ].form ) == 0 )
            {                
                // extract keywords
                return search;
            }
        }
        
        // no major search m_searchProviders found, return empty string
        return "";
    },
    
    // extract a domain value from a document referrer string
    GetDomain : function( i )
    {   
        var regex  = "(?:http|https)://(.*?)/";
             
        if ( i && i.length > 0 )
        {
            var matches = i.match( regex );
            
            if ( matches && matches.length > 1 )
            {
                return encodeURIComponent( matches[ 1 ] );
            }
        }
        
        return "";
    },
    
    // gets a querystring value
    GetQuerystringValue : function( s, u )
    {
        s += "=";
        var h  = u ? u : window.location.href,
            ss = h.indexOf( s ),
            a  = "&";
        q = h.indexOf( '?' );
        if ( q > 0 && ss > q )
        {
            sh = h.substring( ss + s.length );
            return sh.indexOf( a ) > 0 ? 
                       sh.substring( 0, sh.indexOf( a ) ) : 
                       sh;
        }
        return "";
    },
    
    /**************************************************************************
     ** INTERNAL PROPERTIES
     *************************************************************************/

    // event listeners
    m_actionListeners : new Array(),

    // time pivot in seconds (used for unload event)
    m_timePivot : 5,

    // image obj
    m_image : new Image(),

    // name value pairs
    m_dataMap :
    {            
        // single values
        single : 
        {
            url     : "switch.atdmt.com",  // base atlas url
            type    : "action",            // denotes event type
            project : "",                  // project name
            version : "v3"                 // denotes atlas version
        },
        
        // name value pairs
        pair : 
        {
            language   : { value : navigator.language ? 
                                   navigator.language : 
                                   navigator.browserLanguage },  // user-agent language
            country    : { value : "" },                         // country
            location   : { value : "" },                         // location value (i.e., page name)
            action     : { value : "", reset : 1 },              // action (e.g., "click" or "view")
            actionname : { value : "", reset : 1 },              // actionname (e.g., "privacy" or "legal")
            section    : { value : "", reset : 1 },              // section (e.g., "Confirmation" or "Footer")
            source     : { value : "" },                         // source (querystring value of parameter "source")
            time       : { value : "" },                         // timeonpage (should be # of seconds on page)
            resolution : { value : screen.width + "x" + 
                                   screen.height },              // screen resolution
            search     : { value : "" },                         // search engine
            keywords   : { value : "" },                         // search keywords
            domain     : { value : "" },                         // url domain
            url        : { value : "" }                          // url (document.referrer value)
        },
            
        // builds out a URL
        buildUrl : function()
        {
            // url uber base
            var u = [ "http:/" ];
            
            // add singles
            for ( var s in this.single )
            {
                // add value
                u.push( this.single[ s ] );
            }
            
            // add doubles
            for ( var p in this.pair )
            {
                // get value
                var v = this.pair[ p ].value;
                
                // do null?
                if ( v != "" )
                {
                    // add name and value
                    u.push( p + "." + v );
                }
                
                // reset?
                if ( this.pair[ p ].reset )
                {
                    // set to null
                    this.pair[ p ].value = "";
                }
            }
            
            // return completed url
            return u.join('/');
        }
    },
    
    m_searchProviders :
    {
        Live   : { form : "http://search.live.com/results.aspx?", key : "q"  },
        Google : { form : "http://www.google.com/search?",        key : "q"  },
        Yahoo  : { form : "http://search.yahoo.com/search?",      key : "p"  },
        Ask    : { form : "http://www.ask.com/web?",              key : "q"  },
        Baidu  : { form : "http://www.baidu.com/s?",              key : "wd" }    
    },
    
    /**************************************************************************
     ** TRACKING METHODS
     *************************************************************************/

    // handle atlas tracking event (note: this is meant to be bound to an event handler, do not call directly!)
    Click : function()
    {   
        // fire new event
        ( new Atlas.Event() ).Send();
    },
    
    // atlas action method
    Action : function( action )
    {
        // groom it
        var a = this.CleanString( action );
        
        // split based on delimiter
        var p = a.split( "|" );
        
        // iterate through parts
        for ( var i = 0; i < p.length; ++i )
        {
            // pivot on index
            switch ( i )
            {
                // set action
                case 0 : 
                    this.m_dataMap.pair.action.value = p[ i ];
                    break;                    
                // set actionname
                case 1 : 
                    this.m_dataMap.pair.actionname.value = p[ i ];
                    break;                
                // set section
                case 2 : 
                    this.m_dataMap.pair.section.value = p[ i ];
                    break;
            }
        }
        
        // build url
        var url = this.m_dataMap.buildUrl();
        
        // load it
        this.LoadImage( url );      
        
        // notify listeners
        for ( var i = 0; i < this.m_actionListeners.length; ++i )
        {
            // save bytes w/ a shortcut reference
            var cb = this.m_actionListeners[ i ];
            
            // invoke callback                
            if ( typeof cb == 'function' )
                cb( url );
        }
    },
    
    // atlas click event
    View : function()
    {
        // invoke view action
        this.Action( "view" );
    },

    /**************************************************************************
     ** EVENT METHODS
     *************************************************************************/    
        
    // event handler for actions
    OnAction : function( callback )
    {
        // add callback
        this.m_actionListeners.push( callback );
    },

    // atlas event obj
    Event : function()
    {
        // self reference
        var me = this;
        
        // get source
        me.anchor = getAnchor( event.srcElement );
        
        // send it
        this.Send = function()
        {
			var link = me.anchor;

			// check if ready
            if( !link )
                return;

			// get track value
			var track = link.getAttribute('track');
			track = (!track || track.length == 0) ? link.id : track;
			if (!track || track.length == 0)
				return;

            // concat url
            Atlas.Action( track );
        };
        
        // get source of click
        function getAnchor( el )
        {
            while( el && !( el.tagName == 'A' ) )
                el = el.parentNode;
            return el;
        };
    },
    
    // fire an action event on page unload
    BindUnloadEvent : function( a )
    {
        // start time
        var then = new Date();
        
        // bind event to window object
        window.attachEvent( "onunload", function()
            {
                // get minutes and seconds rounded
                var s = Math.round( 
                    ( ( new Date() ).getTime() - then.getTime() ) / 1000 );
                
                // set formatted time value
                Atlas.m_dataMap.pair.time.value = s;
                
                // fire!
                Atlas.Action( "unload" );
            } );
    },

    /**************************************************************************
     ** UTILITY METHODS
     *************************************************************************/
    
    // loads and image
    LoadImage : function( i )
    {            
        // load new image with a cache-killer param attached
        Atlas.m_image.src = i + "/?" + Math.random();
    },

    // cleans up a string and removes 'bad' characters
    CleanString : function( i )
    {
        return i.replace( /\/|\?|&|\.|#/g, "_" );
    }
}

/******************************************************************************
 ** CROSS PLATFORM ATTACH EVENTS
 *****************************************************************************/

// binds IE-style event handling to a target
function __bindEventHdlr( target )
{
    if( target && !target.attachEvent )
    {
        target.attachEvent = function( type, callback )
        {
            type=type.substring(2);
            
            target.addEventListener(type,GenWindowEvent,false);
            target.addEventListener(type,callback,false);
            
            function GenWindowEvent(e) 
            {
                try
                {
                    var i=0; // safari fix to prevent infinite loops
                    while ( e.target && 
                            e.target.nodeType != 1 && 
                            ++i < 50 ) 
                        e.target=e.target.parentNode;
                }
                catch(ex)
                {
                    try
                    {
                        e.target = null;
                    }
                    catch(edummy)
                    {
                    }
                }
                e.srcElement = e.target;
                window.event = e;
            }   
        }
    }
}

// setup window and document objects
__bindEventHdlr( window );
__bindEventHdlr( document );
