/**
 * jQuery plugin to generate profile card hovers for links to user profiles.
 */
;(function($){
  /**
   * Reveals a profile card (after a set delay) near the profile link that
   * triggered it.
   *
   * @param jQuery $profileCard
   * @param jQuery $profileLink
   */
   var showProfileCard = function($profileCard, $profileLink) {
    setTimeout(function(){
      if ($profileLink.attr('profileCardHovering') && $profileCard.attr('profileCardVisible')) {
        // Ensure no other profile cards are visible
        $('div.profileCard').not($profileCard[0]).hide();
        
        // Reveal this profile card if it is presently hidden
        if ($profileCard.is(':hidden')) {
          // Fetching the width dynamically is unreliable, so set a constant
          var cardWidth = 370;
          
          var offset = $profileLink.offset();
          var posX = offset.left + $profileLink.width();
          var posY = offset.top;
          
          // Determine visible edge of the window and check horizontal position
          if ($(window).width() + $(window).scrollLeft() < posX + cardWidth) {
            posX = offset.left - cardWidth;
          }
          
          $profileCard.css({ 'position': 'absolute', 'top': posY, 'left': posX });
          $profileCard.show();
        }
      }
    }, 500);
    
    $profileCard.attr('profileCardVisible', true);
  };
  
  /**
   * Hides a profileCard (after a set delay).
   *
   * @param jQuery $profileCard
   * @param jQuery $profileLink
   */
  var hideProfileCard = function($profileCard, $profileLink) {
    setTimeout(function(){
      if (!$profileLink.attr('profileCardHovering') && !$profileCard.attr('profileCardVisible')) {
        $profileCard.hide();
      }
    }, 500);
    
    $profileCard.removeAttr('profileCardVisible');
  };
  
  /**
   * Generates a DOM ID string from a profile username.
   *
   * @param string username
   * @return string
   */
  var makeIdFromUsername = function(username) {
    /* Note: some legacy usernames may have characters in them which must be
     * removed when generating an id attribute.  In order to prevent most
     * conflicts, we'll strip these characters and append the string length.
     */
    username = username.replace(/[^\-\w]/, '');
    return 'profileCard_' + username + username.length;
  };
  
  /**
   * Initialize the profile card hover on a set of elements.
   * 
   * @return jQuery
   */
  $.fn.profileCard = function() {
    
    // Ensure we have a selection before continuing
    if (!this.length) {
      return this;
    }
    
    // Ensure the card container div exists
    if (!$('#profileCardContainer').length) {
      $('body').append('<div id="profileCardContainer"></div>');
    }
    
    this
      .filter(function() {
        var $profileLink = $(this);
        
        // Allow a parent class to suppress display of the profile card
        if ($profileLink.parent('.nocard').length) {
          return false;
        }
        
        var match = /\/user\/([^#\?\/]+)\/?$/.exec($profileLink.attr('href'));
        
        if (match === null) {
          return false;
        }
        
        $profileLink.attr('profileCardUsername', match[1]);
        return true;
      })
      .bind('mouseenter', function(){
        var $profileLink = $(this).attr('profileCardHovering', true);
        var profileCardId = makeIdFromUsername($profileLink.attr('profileCardUsername'));
        
        // Create the profile card for this user if it doesn't already exist
        if (!$('#' + profileCardId).length) {
          // Specify a redirect_url parameter for the profileCard action
          var data = { redirect_url: window.location.href };
          
          // See #7476 for explanation regarding split closing tag on next line
          $('<div class="profileCard" id="' + profileCardId + '"></di' + 'v>')
            .hide()
            .appendTo('#profileCardContainer')
            .load($profileLink.attr('href') + '/profileCard', data, function(){
              // Bind event handlers after our content loads
              $(this)
                .bind('mouseenter', function(){ showProfileCard($(this), $profileLink); })
                .bind('mouseleave', function(){ hideProfileCard($(this), $profileLink); });
            });
        }
        
        // Display the profile card relative to the profile anchor's position
        showProfileCard($('#' + profileCardId), $profileLink);
      })
      .bind('mouseleave', function(){
        var $profileLink = $(this).removeAttr('profileCardHovering');
        var $profileCard = $('#' + makeIdFromUsername($profileLink.attr('profileCardUsername')));
        hideProfileCard($profileCard, $profileLink);
      });
    
    return this;
  };
  
  // Default initialization
  $(function(){ $('a.profilecard').profileCard(); });
})(jQuery);