﻿ContextualPopup.prototype = new Object();
ContextualPopup.prototype.constructor = ContextualPopup;

ContextualPopup.prototype.show = function() {
  // Determine where to display the popup based on the position of the parent
  // element on the page
  var bodyWidth = $("body").width();
  var visibleHeight = $(window).height();
  var scrollPosition = $(window).scrollTop();
  var parentOffset = this.parent.offset();
  var parentWidth = this.parent.innerWidth();
  var parentHeight = this.parent.innerHeight();
  
  // Set display to block & visibility to hidden so that we may measure
  // the popup
  this.container.css({
    top: 0,
    left: 0,
    height: "auto",
    visibility: "hidden",
    width: this.width - (ContextualPopupController.NotchWidth - ContextualPopupController.BorderWidth),
    paddingLeft: 0,
    paddingRight: 0
  });
  
  var popupWidth = this.container.innerWidth();
  var popupHeight = this.container.innerHeight();
  var popupCenterOffset = parentOffset.top + (parentHeight / 2);
  
  // Show the popup to the left of the parent if the parent is on the right
  // side of the page
  var showOnLeft = parentOffset.left >= (bodyWidth / 2);
  
  // Default to displaying the popup vertically centered to the
  // parent element's position
  var top = popupCenterOffset - (popupHeight / 2);
  var bottom = top + popupHeight;
  var notchOffset = (popupCenterOffset - top) - (ContextualPopupController.NotchHeight.Center / 2);
  var notchStyle = showOnLeft ? "contextual-popup-notch-right" : "contextual-popup-notch-left";
  
  // Check if we should align the popup to the top or bottom
  // of the parent instead
  if (top < scrollPosition + ContextualPopupController.WindowEdgeSpacing) {
    // The top of the popup is out of view - check if the popup would fit
    // into view if we pushed it down so that the top is in view
    if (visibleHeight >= popupHeight + ContextualPopupController.WindowEdgeSpacing) {
      top = scrollPosition + ContextualPopupController.WindowEdgeSpacing;
      
      // Don't allow the notch to float below the bottom edge of the parent
      if (top > parentOffset.top + parentHeight)
        top = parentOffset.top + parentHeight;
      
      bottom = top + popupHeight;
      notchOffset = (popupCenterOffset - top) - (ContextualPopupController.NotchHeight.Center / 2);
      
      // If the notch is flowing outside of the bounds of the container,
      // switch to a top-corner style
      if (notchOffset < 0) {
        notchOffset = 0;
        notchStyle = showOnLeft ? "contextual-popup-notch-right-top" : "contextual-popup-notch-left-top";
      }
    }
  } else if (bottom > scrollPosition + (visibleHeight - ContextualPopupController.WindowEdgeSpacing)) {
    // The bottom of the popup is out of view - check if the popup would fit
    // into view if we pushed it up so that the bottom is in view
    if (visibleHeight - ContextualPopupController.WindowEdgeSpacing >= popupHeight) {
      bottom = scrollPosition + (visibleHeight - ContextualPopupController.WindowEdgeSpacing);
      
      // Don't allow the notch to float above the top edge of the parent
      if (bottom < parentOffset.top)
        bottom = parentOffset.top;
      
      top = bottom - popupHeight;
      notchOffset = (popupCenterOffset - top) - (ContextualPopupController.NotchHeight.Center / 2);
      
      // If the notch is flowing outside of the bounds of the container,
      // switch to a bottom-corner style
      if (notchOffset + ContextualPopupController.NotchHeight.Center >= popupHeight) {
        notchOffset = popupHeight - ContextualPopupController.NotchHeight.Bottom;
        notchStyle = showOnLeft ? "contextual-popup-notch-right-bottom" : "contextual-popup-notch-left-bottom";
      }
    }
  }
  
  // Set up notch
  this.notch.removeClass();
  this.notch.addClass(notchStyle);
  if (showOnLeft) {
    this.container.css({
      paddingRight: ContextualPopupController.NotchWidth - ContextualPopupController.BorderWidth
    });
    this.notch.css({
      top: notchOffset,
      left: this.width - ContextualPopupController.NotchWidth
    });
  } else {
    this.container.css({
      paddingLeft: ContextualPopupController.NotchWidth - ContextualPopupController.BorderWidth
    });
    this.notch.css({
      top: notchOffset,
      left: 0
    });
  }
  
  var left = showOnLeft ? parentOffset.left - this.width : parentOffset.left + parentWidth;
  
  // Fix for popups in IE6 when positioned over select elements
  if (ContextualPopupController.iframe != null) {
    ContextualPopupController.iframe.css({
      top: top,
      left: left,
      width: popupWidth,
      height: popupHeight,
      display: "block"
    });
  }
  
  // Move and display the popup
  this.container.css({
    visibility: "visible",
    top: top,
    left: left
  });
};

ContextualPopup.prototype.hide = function() {
  // Fix for popups in IE6 when positioned over select elements
  if (ContextualPopupController.iframe != null) {
    ContextualPopupController.iframe.css({
      display: "none"
    });
  }
  
  this.container.css({
    visibility: "hidden",
    height: 0
  });
};

function ContextualPopup(parent, content, width) {
  var _this = this;
  this.parent = parent;
  this.content = content;
  this.width = width;
  
  // Create container element for this popup and move the content into it
  this.container = $("<div class='contextual-popup-container'></div>");
  $("body").append(this.container);
  this.container.append(this.content);
  
  // Create notch element
  this.notch = $("<div></div>");
  this.container.append(this.notch);
  
  // Set up rollover events
  this.parent.mouseenter(function() {
    _this.show();
  });
  this.parent.mouseleave(function() {
    _this.hide();
  });
  
  // Perform any image fixes necessary in this popup
  UIUtilities.fixImages(function() {
    return _this.content.find("img.ie6PngFix").add(_this.parent.find("img.ie6PngFix"));
  });
}

var ContextualPopupController = {
  Width: 283, // This includes the notch width
  BorderWidth: 4,
  NotchWidth: 24,
  NotchHeight: {
    Top: 16,
    Center: 31,
    Bottom: 16
  },
  WindowEdgeSpacing: 20,
  Shadow: {
    BlurRadius: 20,
    Offset: 3,
    Opacity: 0.2
  },
  
  iframe: null,
  popups: new Array(),
  
  init: function(ignoreNoPopupInstructions) {
    this.popups = new Array();
    $(".contextual-popup-container").remove();
    
    if (ContextualPopupController.iframe == null && UIUtilities.BrowserIsIE6) {
      ContextualPopupController.iframe = $("<iframe class='select-block' style='visibility: hidden;'></iframe>");
      $("body").append(ContextualPopupController.iframe);
    }
    
    var parents = $(".contextual-popup-parent");
    for (var i=0; i<parents.length; i++) {
      var parent = $(parents[i]);
      
      // Find content blocks associated with this parent
      var content = parent.find(".contextual-popup-content");
      if (content.length <= 0)
        continue;
      
      // Make sure this isn't inside of a filter container which needs to
      // create the popups as filter settings change
      if (ignoreNoPopupInstructions != true) {
        var ancestor = parent.parent();
        while (ancestor.length > 0) {
          if (ancestor.hasClass("no-popup-init"))
            break;
          
          ancestor = ancestor.parent();
        }
        if (ancestor.length > 0)
          continue;
      }
      
      var popup = new ContextualPopup(parent, content, ContextualPopupController.Width);
      this.popups.push(popup);
    }
  }
};

// Custom JQuery selector for selecting items that are not decendants of the 
