(function($) {
  $.fn.track = function(options) {
    // Add event handler to all matching elements
    return this.each(function() {
      var element = $(this);

      // Prevent an element from being tracked multiple times.
      if (element.hasClass('tracked')) {
        return false;
      } else {
        element.addClass('tracked');
      } 

      // Use default options, if necessary
      var settings = $.extend({}, $.fn.track.defaults, options);

      // Merge custom options with defaults.
      var category   = evaluate(element, settings.category),
          action     = evaluate(element, settings.action),
          label      = evaluate(element, settings.label),
          value      = evaluate(element, settings.value),
          event_name = evaluate(element, settings.event_name),
          message = "category:'" + category + "' action:'" + action + "' label:'" + label + "' value:'" + value + "'";

      // Debug if enabled
      debug('Tracking ' + event_name + ' ' + message);

      // Bind the event to this element. 
      element.bind(event_name, function() {
        
        // Should we skip internal links?
        var skip = settings.skip_internal && (element[0].hostname == location.hostname);
        if (!skip && _gaq != undefined) {
          _gaq.push([ '_trackEvent', category, action, label, value ]);
          debug('Tracked ' + message);
        } else {
          debug('Skipped ' + message);
        }
        return true;
      });
    });
    
    /**
     * Checks whether a setting value is a string or a function.
     * 
     * If second parameter is a string: returns the value of the second parameter.
     * If the second parameter is a function: passes the element to the function and returns function's return value.
     */
    function evaluate(element, text_or_function) {
      if(typeof text_or_function == 'function') {
        text_or_function = text_or_function(element);
      }
      return text_or_function;
    };
    
  };

  // Default tracking options
  $.fn.track.defaults = {
    category      : function(element) { return (element[0].hostname == location.hostname) ? 'internal' : 'external'; },
    action        : 'click',
    label         : function(element) { return element.attr('href'); },
    value         : null,
    skip_internal : false,
    event_name    : 'click',
    debug         : false
  };

  // Send debugging information if enabled and the browser supports it
  function debug(message) {
    if (typeof console != 'undefined' && typeof console.log != 'undefined' && $.fn.track.defaults.debug) {
      console.log(message);
    }
  };

})(jQuery);

