$(function() {
  var fn = function(id, debug) {
    var me = this;
    this.id = id;
    this.debug = debug;
    this.ready = false;
    this.log = function(a) {
      if (me.debug) log(a);
    };    
    this.init = function() {
      window._gaq = window._gaq || [];
      window._gaq.push(['_setAccount', me.id]);
      window._gaq.push(['_trackPageview']);
      var src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
      var tag = document.createElement('script');
      tag.type = 'text/javascript';
      tag.async = true;
      tag.src = src;

      var s = document.getElementsByTagName('script')[0];
      s.parentNode.insertBefore(tag, s);
      me.log('gaq loaded for account: ' + me.id);
      me.ready = true;
    };
    this.track = function(o) {
      if (!me.ready) me.init();
      var e = [ '_trackEvent', o.category, o.action ];
      if (o.label) e.push(o.label);
      if (!isNaN(o.value)) e.push(parseInt(o.value, 10));
      window._gaq.push(e);
      me.read = true;
      me.log('Event tracked: ' + e);
    };
    this.prepFormEventOptions = function(o, def) {
      o = o || {};
      o.category = o.category || def.category || 'Forms';
      o.action = o.action || def.action || 'Unnamed Form';
      o.label = o.label || def.label || 'Unknown Event';
      o.value = isNaN(o.value) ? 'x' : parseInt(o.value,10);
      return o;
    };
    this.trackFormLoad = function(formName, a) {
      a = me.prepFormEventOptions(a, { action: formName, label: 'Load' });
      me.track(a);
    };
    this.trackFormSubmit = function(formName, a) {
      a = me.prepFormEventOptions(a, { action: formName, label: 'Success' });  
      me.track(a);
    };
    this.trackFormError = function(formName, a) {
      a = me.prepFormEventOptions(a, { action: formName, label: 'Error' });
      me.track(a);
    };
    this.prepTrackDownloadEventOptions = function(o, def) {
      o = o || {};
      o.category = o.category || def.category || 'Downloads';
      o.action = o.action || def.action || 'Unknown Extension';
      o.label = o.label || def.label || 'Unknown File Name';
      o.value = isNaN(o.value) ? 'x' : parseInt(o.value, 10);
      return o;
    };
    this.trackDownloads = function(exts, a) {
      me.log('Extensions added to tracking: ' + exts);
      $('a:not(.no-tracking)').each(function(e) {
        var a = $(this);
        var key = me.id + '_trackDownloads';
        var existingExts = a.data(key) || [];
        for(var i = 0; i < exts.length; i++) {
          var ext = '.' + $.trim(exts[i]).replace('.', '');
          if (ext.length > 0) {
            existingExts.push({
              ext: ext,
              event: a
            });
          }
        }
        a.data(key, existingExts);
        
        if (!a.hasClass('downloadsTracked')) {
          a.addClass('downloadsTracked');
          a.click(function(event) {
            var a = $(this);
            var href = a.attr('href');
            if (!href || href.length == 0 || href.indexOf('#') === 0) {
                return;
            }
            var hrefArr = href.split('/');
            var cleanHref = hrefArr[hrefArr.length-1].split('.')[0];
            var ext = a.attr('href');
            var trackedExts = a.data(key);
            var isTracked = false;

            for(var i = 0; i < trackedExts.length; i++) {
              var tracker = trackedExts[i];
              if (ext.indexOf(tracker.ext) === ext.length - tracker.ext.length) {
                event.preventDefault();
                var e = me.prepTrackDownloadEventOptions(tracker.event, { action: tracker.ext, label: cleanHref });
                me.track(e);
                
                setTimeout(function() {
                  window.location = href;
                }, 200);
                return;
              }
            }
          });
        }
      });
    };
    this.prepTrackOutboundLinkOptions = function(o, def) {
      o = o || {};
      o.category = o.category || def.category || 'Outbound Links';
      o.action = o.action || def.action || 'Unknown Domain';
      o.label = o.label || def.label || 'Unknown URL';
      o.value = isNaN(o.value) ? 'x' : parseInt(o.value, 10);
      return o;
    };
    this.trackOutboundLinks = function(o) {
      me.log('Outbound link-tracking is activated.');
      $('a').live('click', function(event) {
        var a = $(this);
        var href = a.attr('href');
        if (!href || href.length === 0) {
          return; 
        }
        href = href.toLowerCase();
        
        if (href.indexOf('http') === 0) {
          var domain = href.split(/^https?:\/\/[^\/]\//)[0].split('//')[1].split('/')[0];
          var e = me.prepTrackOutboundLinkOptions(o, { action: domain, label: href });
          me.track(e);
        }
      });
    };
  };
    
  var $meta = $('head:first meta[name=google analytics]');
  $meta.each(function() {
    var me = $(this);
    var id = $.trim(me.attr('content'));
    var debug = $.trim(me.attr('data-debug')).toLowerCase() === 'true';
    var domVar = $.trim(me.attr('data-domVar')) || 'ga';
    var trackFiles = ($.trim(me.attr('data-trackFiles')) || '').split(/[;,]/g);
    var trackOutboundLinks = $.trim(me.attr('data-trackOutboundLinks')).toLowerCase() === 'true';
    
    if(window[domVar]) {
      gaLog('domVar "' + domVar + '" is already registered.');
      return;
    }
    else {
      window[domVar] = new fn(id, debug);
      window[domVar].init();
      if (trackFiles[0].length > 0) {
        window[domVar].trackDownloads(trackFiles);
      }
      if(trackOutboundLinks) {
        window[domVar].trackOutboundLinks();
      }
    }
  });
});

window.log = function(){
  log.history = log.history || [];
  log.history.push(arguments);
  arguments.callee = arguments.callee.caller;  
  if(this.console) console.log( Array.prototype.slice.call(arguments) );
};
