window.VIP = {
  assetsLoaded: 'not-loaded',
  productRecipient: 0,
  recurringPayments: 1,
  productType: '',
  vipData: false,
  vipLevel: false,
  vipModifier: false,

  // VIP's URL
  url: null,

  // Current Users age
  age: null,

  // Marker to know if we preloaded the files required to support friend selectors.
  friendSelectorLoaded: 'notInitialized',

  // Disables the friend selector, and forces "Myself" only
  isGiftingEnabled: true,

  uiComponentHelper:
  {
    /**
     * uiComponents default to this.  If a uiComponent does not need to be
     * displayed, it does not have to be put in the paymentType.settings.uiComponents
     * object.
     */
    NEVER_SHOW: 'never',
    /**
     * Show the uiComponent only if the current purchase is a gift for another user.
     */
    SHOW_ON_GIFT: 'ongift',
    /**
     * Show the uiComponent only if the current purchase is not a gift for another user.
     */
    NOT_ON_GIFT: 'notgift',
    /**
     * Always display the uiComponent.
     */
    ALWAYS_SHOW: 'always',
    /**
     * Allow more human readable selectors for the various uiComponents.
     */
    mapping: {
      'SelectRecipientDiv': "vip-selectGR",
      'PaymentOptionsDiv': "vip-selectPT",
      'ProductsDiv': "vip-selectPP",
      'MonthsDiv': "vip-cashOnly",
      'ProductRequestDiv': "vip-selectPRL",
      'RequestFormDiv': "vip-selectPRF",
      'RequestParentFormDiv': "vip-selectPRPF",
      'VIPSubtextDiv': "vip-subText",
      'VIPSupertextDiv': "vip-superText",
      'ZongVIPSubtextSpan' : "vip-downgrading-zongOnly"
    },
    
    /**
     * Given a uiComponent and a paymentType, this function returns if the uiComponent
     * should be visible.
     * 
     * @param uiComponent string A uiComponent's ID or name from the uiComponentHelper.mapping object
     * @param paymentType string A payment type from the paymentTypes object
     * @return boolen
     */
    isVisible : 
      function( uiComponent, paymentType )
      {
        //Allow the use of more human readable keys for the various ui component divs
        if( VIP.uiComponentHelper.mapping[uiComponent] )
        {
          uiComponent = VIP.uiComponentHelper.mapping[uiComponent];
        }

        if( !paymentType || !VIP.paymentTypes[paymentType] || !uiComponent || !VIP.paymentTypes[paymentType].settings.uiComponents[uiComponent] )
        {
          return false; 
        }

        if( VIP.util.isGift() === true )
        {
          return ( VIP.paymentTypes[paymentType].settings.uiComponents[uiComponent] === 'always'  
            || VIP.paymentTypes[paymentType].settings.uiComponents[uiComponent] === 'ongift' );
        }
        else
        {
          return ( VIP.paymentTypes[paymentType].settings.uiComponents[uiComponent] === 'always'  
            || VIP.paymentTypes[paymentType].settings.uiComponents[uiComponent] === 'notgift' );
        }
      },
   
    /**
     * Builds a new uiComponent and appends it to the VIP popup
     * TODO: move all uiComponents here
     * 
     * @param string A uiComponent's ID or name from the uiComponentHelper.mapping object
     * @return void
     */
    initUIComponent :
      function( uiComponent )
      {
        var html = '';
    
        switch( uiComponent )
        {
          case 'vip-selectPRL':
            //Request product div.  This is a copy of the product list div.  That div is guaranteed
            //to be available so clone it and update the text as necessary.
            var html = '<div id="vip-selectPRL" class="vip-select">' + 
            $('#vip-selectPP')
              .clone()
              .find('select')
              .attr( 'id', 'vip-products-request')
              .hide()
              .end()
              .find('h3')
              .html( VIP.productTypeVerbiage[ VIP.productType ].productRequestText )
              .end()
              .html() 
            + '</div>';
  
            $("#vip-selectPP").after( html );
  
            //Make sure the VIP modifier doesn't get displayed when requesting L$/VIP
            VIP.uiComponentHelper.toggleVIPModifier( false, 'vip-products-request' );
  
            $("#vip-products-request").show();
            break;
          case 'vip-selectPRPF':
            html = '<div id="vip-selectPRF" class="vip-select">';
            html += '<h3>' + VIP.productTypeVerbiage[ VIP.productType ].requestText + '</h3>';
            html += '<form name="vipPopupGiftRequestForm" id="vipPopupGiftRequestForm">';
            html += '<ul id="vipFriendRequestOptions">';
            html += '<li>';
            html += '<div style="width:122px; text-align:right; padding:3px; margin:3px auto; float:left; font-weight:bold;">Recipient:</div>';
            html += '<div style="width:200px; margin: 3px auto; padding: 3px; float:left; text-align:left;">';
            html += '<input name="PRF-recipient" value="Mom" type="radio" class="radio required" checked /> Mom';
            html += '<input name="PRF-recipient" value="Dad" type="radio" class="radio required" /> Dad';
            html += '<input name="PRF-recipient" value="Other" type="radio" class="radio required" /> Other';
            html += '</div>';
            html += '</li>';
            html += '<li id="PRF-recipient-name-li" style="display:none;"><div style="width:122px; text-align:right; padding:3px; margin:3px auto; float:left; font-weight:bold;">Recipient\'s Name:</div> <input name="PRF-recipient-name" id="PRF-recipient-name" value="" type="text" class="text" maxlength="10" /></li>';
            html += '<li><div style="width:122px; text-align:right; padding:3px; margin:3px auto; float:left; font-weight:bold;">Recipient\'s Email:</div> <input name="PRF-recipient-email" id="PRF-recipient-email" value="" type="text" class="text required email" /></li>';
            html += '<li><div style="width:122px; text-align:right; padding:3px; margin:3px auto; float:left; font-weight:bold;">Your Real First Name:</div> <input name="PRF-real-name" id="PRF-real-name" value="" type="text" class="text required" maxlength="10" /></li>';
            html += '</ul>';
            html += '</form>';
            html += '</div>';
            
            if( $('#vip-selectPRL').size() > 0 )
            {
              $("#vip-selectPRL").after( html );
            }
            else
            {
              $("#vip-selectPP").after( html );
            }
            
            $('#vipPopupGiftRequestForm').validate({
              messages: {
                'PRF-recipient-name': {
                  required: 'Recipient name is required'
                },
                'PRF-recipient-email': {
                  required: 'Recipient email is required'
                },
                'PRF-real-name': {
                  required: 'Your real name is required'
                }
              }
            });
            
            /**
             * Set up onclick events for the radio buttons.  The Mom/Dad radio buttons
             * hide the recipient name field, the Other radio button displays it.
             */
            $("#vipFriendRequestOptions :radio[value!='Other']").click( function() {
              $("#PRF-recipient-name-li").hide();
              $("#PRF-recipient-name").removeClass( 'required' );
              $('#vipPopup').centerOnScreen();
            });
            
            $("#vipFriendRequestOptions :radio[value='Other']").click( function() {
              $("#PRF-recipient-name-li").show();
              $("#PRF-recipient-name").addClass( 'required' );
              $('#vipPopup').centerOnScreen();
            });
            break;
          case 'vip-selectPRF':
            html = '<div id="vip-selectPRF" class="vip-select">';
            html += '<h3>' + VIP.productTypeVerbiage[ VIP.productType ].requestText + '</h3>';
            html += '<form name="vipPopupGiftRequestForm" id="vipPopupGiftRequestForm">';
            html += '<ul id="vipFriendRequestOptions">';
            html += '<li><div style="width:122px; text-align:right; padding:3px; margin:3px auto; float:left; font-weight:bold;">Recipient\'s Name:</div> <input name="PRF-recipient-name" id="PRF-recipient-name" value="" type="text" class="text required" maxlength="10" /></li>';
            html += '<li><div style="width:122px; text-align:right; padding:3px; margin:3px auto; float:left; font-weight:bold;">Recipient\'s Email:</div> <input name="PRF-recipient-email" id="PRF-recipient-email" value="" type="text" class="text required email" /></li>';
            html += '<li><div style="width:122px; text-align:right; padding:3px; margin:3px auto; float:left; font-weight:bold;">Your Real First Name:</div> <input name="PRF-real-name" id="PRF-real-name" value="" type="text" class="text required" maxlength="10" /></li>';
            html += '</ul>';
            html += '</form>';
            html += '</div>';
  
            if( $('#vip-selectPRL').size() > 0 )
            {
              $("#vip-selectPRL").after( html );
            }
            else
            {
              $("#vip-selectPP").after( html );
            }
            
            $('#vipPopupGiftRequestForm').validate({
              messages: {
                'PRF-recipient-name': {
                  required: 'Recipient name is required'
                },
                'PRF-recipient-email': {
                  required: 'Recipient email is required'
                },
                'PRF-real-name': {
                  required: 'Your real name is required'
                }
              }
            });
            break;
        }
      },
    
    /**
     * Updates the available payment options
     * Updates the visible VIP popup UI elements
     * Updates the VIP modifier (for L$ only)
     * Toggles the disabled VIP access level (for VIP access only)
     * Recenters VIP popup
     * 
     * @return void
     */
    onUIChange :
      function( )
      {
        //Update uiComponents based on paymentType
        var paymentType = $('#vipPaymentTypes input:checked').val();
        if( paymentType )
        {
          $.each(VIP.uiComponentHelper.mapping, function( key, uiComponent ) {
            if( VIP.uiComponentHelper.isVisible( uiComponent, paymentType ) )
            {
              var $component = $('#' + uiComponent);
              if( $component.size() == 0 )
              {
                VIP.uiComponentHelper.initUIComponent( uiComponent );
                $component = $('#' + uiComponent);
              }
  
              if( $component.size() > 0 )
              {
                $component.show();
              }
            }
            else
            {
              $('#' + uiComponent).hide();
            }
          });
        }
        
        VIP.uiComponentHelper.toggleFreeTrial( !VIP.util.isGift(), paymentType );
        VIP.uiComponentHelper.toggleVIPModifier( !VIP.util.isGift() );
        VIP.uiComponentHelper.toggleVIPDisabled( VIP.util.isGift(), paymentType );

        //Update paymentTypes based on gift status
        $.each(VIP.paymentTypes, function( paymentType, attributes ) {
          var allowsGifting = attributes.settings.allowsGifting;
          if ( typeof allowsGifting == 'object' )
          {
            allowsGifting = allowsGifting[VIP.productType];
          }
          var isVisible = ( attributes.settings.enabled === true && ( !VIP.util.isGift() || allowsGifting ) );
          VIP.uiComponentHelper.togglePaymentType( paymentType, isVisible );
        });
      
        VIP.uiComponentHelper.btnContinue( VIP.productType );
        
        $('#vipPopup').centerOnScreen();
    },
    
    /**
     * Update the Continue button to use different images based on
     * if the current purchase is a gift
     * 
     * @return void
     */
    btnContinue :
      function( productType )
      {
        if( VIP.util.isGift() )
        {
          $('#vip-btnContinue').html( productType );
          $('#vipPopup').removeClass( 'vip-product-' + productType ).addClass( 'vip-product-' + productType + '-gift' );
        }
        else
        {
          $('#vip-btnContinue').html( productType );
          $('#vipPopup').removeClass( 'vip-product-' + productType + '-gift' ).addClass( 'vip-product-' + productType );
        }
      },
      
    toggleFreeTrial :
      function( enableFlag, paymentType )
      {
        if ( typeof paymentType == 'undefined' )
        {
          if ( "console" in window )
          {
            console.warn( "paymentType was undefined" );
          }
          return false;
        }
        if ( ! VIP.paymentTypes[ paymentType ] )
        {
          if ( "console" in window )
          {
            console.warn( "unrecognized paymentType: " + paymentType );
          }
          return false;
        }

        if ( VIP.paymentTypes[ paymentType ].settings.allowsTrial !== true )
        {
          enableFlag = false;
        }
        
        var $productList = $('#vip-products');
        var originalPrices = $productList.data( 'originalPrices' );
        var usdPrices = $productList.data( 'usdPrices' );
        var originalText = $productList.data( 'originalText' );
        var symbol = $productList.attr('data-currency') === 'USD' ? '$' : '\u00A3'
          
        
        if( enableFlag === true && $productList.attr('data-vip-extra') == 'trial' )
        {
          if ( "console" in window && console.debug )
          {
            console.debug( ' >> Showing FREE trial' );
          }
          $('#freeTrialSubText').show();

          // If able to offer the FREE trial, replace original price (incl symbol and /mo) with "FREE"
          $productList.find('option').each(function() {
            var key = '_' + this.value;
            var t = originalText[ key ].replace( ' for ' + symbol + originalPrices[ key ] + '/mo', ' FREE' );
            $(this).text( t );
          });
        }
        else if ( VIP.paymentTypes[ paymentType ].settings.roundsPrices !== true )
        {
          if ( "console" in window && console.debug )
          {
            console.debug( ' >> Showing full price' );
          }
          $('#freeTrialSubText').hide();

          // Else we're revoking free trial, so replace "FREE" with original price
          $productList.find('option').each(function(){
            $(this).text( originalText[ '_' + this.value ] );
          });
        }
      },
    
    /**
     * Updates the VIP modifier display when purchasing L$.  If a payment option
     * selected or if a gift recipient is selected, the VIP modifiers will be
     * hidden.
     * 
     * @param enableFlag boolean A boolean to turn VIP modifiers on/off
     * @param productList string [Optional] Specify a different product list to update.
     * @return void
     */
    toggleVIPModifier :
      function( enableFlag, productList )
      {
        if( VIP.productType == 'lunchmoney' && VIP.vipModifier !== false )
        {
          if( !productList )
          {
            $products = $('#vip-products option');
          }
          else
          {
            $products = $('#' + productList + ' option');
          }

          if( $products.size() > 0 )
          {
            if( enableFlag === true )
            {
              $products.each( function( key ) {
                var productText = $products.eq(key).html();
                $products.eq(key).html( VIP.vipModifier + ' x ' + productText.replace(/\d\sx\s/, '') );
              });
            }
            else
            {
              $products.each( function( key ) {
                var productText = $products.eq(key).html();
                $products.eq(key).html( productText.replace(/\d\sx\s/, '') );
              });
            }  
          }
        }
      },
      
    /**
     * @param enableFlag boolean A boolean to enable/disable VIP access products
     * @param paymentType string [Optional] If a payment type is supplied, the
     *                      paymentType's allowTrial property will be used
     *                      as well to determine if a product is enabled/disabled
     * @return void
     */
    toggleVIPDisabled :
      function( enableFlag, paymentType )
      {
        if( typeof paymentType != 'undefined' )
        {
          enableFlag = enableFlag || !VIP.paymentTypes[ paymentType ].settings.allowsTrial; 
        }
        
        if ( VIP.productType == 'vip_membership' )
        {
          if ( $('#vip-products option:contains("' + VIP.vipLevel + '"):eq(0)').size() > 0 )
          {
            if( enableFlag === true )
            {
              $('#vip-products option:contains("' + VIP.vipLevel + '"):eq(0)').attr('disabled', '');
            }
            else
            {
              $('#vip-products option:contains("' + VIP.vipLevel + '"):eq(0)').attr('disabled', 'disabled');
            }
          }
        }
      },
    
    /**
     * Show/hide a payment type.  This is used by the uiComponentHelper.onUIChange()
     * function to update the available payment options
     * 
     * @param paymentType string Payment type to enable/disable
     * @param enableFlag boolean A boolean to enable/disable a payment type
     * @return void
     */
    togglePaymentType :
      function( paymentType, enableFlag )
      {
        if( VIP.paymentTypes[paymentType] )
        {
          if( enableFlag === false )
          {
            $('li:has(#vipPayment' + paymentType + ')', '#vipContent').hide();

            if( $('input:checked','#vipPaymentTypes').val() == paymentType )
            {
              $('#vipPayment' + paymentType ).attr('checked', '');
            }
          }
          else
          {
            $('li:has(#vipPayment' + paymentType + ')','#vipContent').show();
          }
        }
      },
      
    /**
     * Remove payment types that are not used for the current product from
     * the DOM.  Called by  initProductList() to cleanup the available
     * payment types.
     */
    removeInvalidPaymentTypes :
      function( )
      {
        $.each(VIP.paymentTypes, function( paymentType, attributes ) {
          
          if( attributes.available[ VIP.productType ] !== true )
          {
            $('li:has(#vipPayment' + paymentType + ')','#vipContent').remove();
          }
        });
      }
  },
  
  /**
   * Payment Types
   * @property string id Identifies a payment type
   * @property string text Displayed next to radio button in popup
   * @property string img Image filename to display next to @text
   * @property object settings
   *   @property bool allowsTrial If false, will hide free trial even if the user is otherwise eligible for it
   *   @property bool roundsPrices If true, selecting this payment type will round all prices to the nearest currency unit
   *   @property string requiresAttr If set, a product must have this attribute to appear available for this payment type
   */
  paymentTypes: 
  {
    Credit: {
      id: 'Credit',
      text: 'Credit Card',
      img: 'credit_cards.gif',
      settings: {
        "allowsTrial": true,
        "allowsGifting": true,
        "roundsPrices": false,
        "enabled": true,
        uiComponents: {
          "vip-selectGR": 'always',
          "vip-selectPT": 'always',
          "vip-selectPP": 'always',
          "vip-cashOnly": 'ongift',
          "vip-subText": 'notgift',
          "vip-superText": 'notgift'
        }
      },
      available: {
        "lunchmoney": true,
        "vip_membership": true
      }
    },
    Zong: {
      id: 'Zong',
      text: 'Cell Phone',
      img: 'pay_mobile.gif',
      settings: {
        "allowsTrial": false,
        "allowsGifting": {
          "lunchmoney" : true,
          "vip_membership" : false
        },
        "roundsPrices": false,
        "requiresAttr": "data-zong",
        "enabled": true,
        uiComponents: {
          "vip-selectGR": 'always',
          "vip-selectPT": 'always',
          "vip-selectPP": 'always',
          "vip-cashOnly": 'ongift',
          "vip-subText": 'notgift',
          "vip-superText": 'notgift',
          "vip-downgrading-zongOnly": 'notgift'
        }
      },
      available: {
        "lunchmoney": true,
        "vip_membership": true
      }
    },
    PayPal: {
      id: 'PayPal',
      text: 'PayPal',
      img: 'paypal.gif',
      settings: {
        "allowsTrial": true,
        "allowsGifting": true,
        "roundsPrices": false,
        "enabled": true,
        uiComponents: {
          "vip-selectGR": 'always',
          "vip-selectPT": 'always',
          "vip-selectPP": 'always',
          "vip-cashOnly": 'ongift',
          "vip-subText": 'notgift',
          "vip-superText": 'notgift'
        }
      },
      available: {
        "lunchmoney": true,
        "vip_membership": true
      }
    },
    Cash: {
      id: 'Cash',
      text: 'Cash/Check/Money Order',
      img: 'pay_ccmo.gif',
      settings: {
        "allowsTrial": false,
        "allowsGifting": true,
        "roundsPrices": true,
        "enabled": true,
        uiComponents: {
          "vip-selectGR": 'always',
          "vip-selectPT": 'always',
          "vip-selectPP": 'always',
          "vip-cashOnly": 'always',
          "vip-subText": 'notgift',
          "vip-superText": 'notgift'
        }
      },
      available: {
        "lunchmoney": true,
        "vip_membership": true
      }
    },
    CashCard: {
      id: 'CashCard',
      text: 'Redeem a 7-Eleven or Target card',
      img: 'stores.gif?2',
      settings: {
        "allowsTrial": false,
        "allowsGifting": false,
        "roundsPrices": false,
        "enabled": true,
        uiComponents: {
          "vip-selectPT": 'always'
        }
      },
      available: {
        "lunchmoney": false,
        "vip_membership": true
      }
    },
    AskParents: {
      id: 'AskParents',
      text: 'Ask Parents to Pay',
      img: 'pay_ask_parents.gif',
      settings: {
        "allowsTrial": false,
        "allowsGifting": false,
        "roundsPrices": false,
        "enabled": false,
        uiComponents: {
          "vip-selectPT": 'always',
          "vip-selectPRPF": 'always'
        }
      },
      available: {
        "lunchmoney": false,
        "vip_membership": true
      }
    },
    AskFriend:
    {
      id: 'AskFriend',
      text: 'Send a Gift Request with 1-Click',
      img: 'pay_gift_request.gif',
      settings: {
        "allowsTrial": false,
        "allowsGifting": false,
        "roundsPrices": false,
        "enabled": false,
        uiComponents: {
          "vip-selectPT": 'always',
          "vip-selectPRF": 'always'
        }
      },
      available: {
        "lunchmoney": false,
        "vip_membership": true
      }
    }
  },
  
  productTypeVerbiage:
  {
    lunchmoney: {
      title: "Buy Lunch Money",
      payTypeSelect: "How would you like to pay for Lunch Money?",
      productSelect: "How much Lunch Money would you like to purchase?",
      friendSelect: "Lunch Money",
      productRequestText: "How much would you like to request?",
      requestText: "Who would you like to send the Gift Request to?",
      maintenance: 'Purchasing Lunch Money is currently down for maintenance.  Please try again later.',
      superText: {
        noLevel: '<a href="javascript:void(0);" class="temp-vip-url">Get More L$ for the Same Price!  Join the VIP Club!</a>'
      },
      subText: {
        hasLevel: 'As a <span id="vip-popup-subtext-levelName">%levelName% VIP Club</span> member, you\'re getting <span class="bold">double Lunch Money</span> for every Lunch Money purchase!' 
      },
      callbacks: {
        onProductChange: function() { 
          VIP.util.checkPaymentProduct();
          VIP.util.cashProductChange();
        },
        onPaymentTypeChange: function() {
          VIP.util.updateProducts( VIP.paymentTypes[ $('#vipPaymentTypes input:checked').val() ] );
          VIP.util.cashPaymentChange();
          VIP.uiComponentHelper.onUIChange();
        },
        productListInit: function() {
          VIP.util.initPrices( );
          VIP.util.updateProducts( VIP.paymentTypes[ $('#vipPaymentTypes input:checked').val() ] );
          VIP.util.cashProductChange( true );
          VIP.uiComponentHelper.removeInvalidPaymentTypes();
        }
      }
    },
    vip_membership: {
      title: "Buy VIP Club Access",
      payTypeSelect: "How would you like to pay for VIP Access?",
      productSelect: "Choose your VIP Level...",
      friendSelect: "VIP Club Access",
      productRequestText: "What level VIP Access would you like to request?",
      requestText: "Who would you like to send the Gift Request to?",
      maintenance: 'VIP Club signup is currently down for maintenance.  Please try again later.',
      subText: {
        hasLevel: '<div class="vip-updown"><span class="vip-upgrading">If you upgrade to a higher VIP level, it will take effect immediately.</span> <span class="vip-downgrading">If you downgrade, your current (higher) level will remain in effect until it expires.</span> <span id="vip-downgrading-zongOnly">If you downgrade and wish to pay using your mobile phone, <b>your current (higher) VIP level will be canceled immediately!</b></span></div>'
      },
      cashOnly: '<h3>How many months?</h3>',
      callbacks: {
        onDOMAppend: function(verbiage) {
          var $qty = $('<select id="vip-quantities"></select>');
          $('#vip-cashOnly').append( $qty );
          if ( $qty.size() > 0 )
          {
            var i;
            for( i = 1; i <= 12; i += 1)
            {
              // Add "x month(s)" option.  Pre-select 3 months
              $qty.append( '<option value="' + i + '"' + (i == 3 ? ' selected="selected"' : '') + '>' + i + ' month' + (i > 1 ? 's' : '') + '</option>' );
            }
          }
          
        },
        onProductChange: function() { 
          VIP.util.checkPaymentProduct();
          VIP.util.cashProductChange();
        },
        onPaymentTypeChange: function() {
          VIP.util.updateProducts( VIP.paymentTypes[ $('#vipPaymentTypes input:checked').val() ] );
          VIP.util.cashPaymentChange();
          VIP.uiComponentHelper.onUIChange();
          VIP.util.vipZongDisclaimer( );
        },
        productListInit: function() {
          VIP.util.initPrices( );
          VIP.util.updateProducts( VIP.paymentTypes[ $('#vipPaymentTypes input:checked').val() ] );
          VIP.util.cashProductChange( true );
          VIP.uiComponentHelper.removeInvalidPaymentTypes();
        }
      }
    }
    },
  
  getPaymentTypes : 
    function ( productsList )
    {
      var payTypes = '';
      var sel = false;
      for ( x in VIP.paymentTypes )
      {
        if ( VIP.paymentTypes.hasOwnProperty( x ) )
        {
          var payType = VIP.paymentTypes[x];
          if ( payType.settings )
          {
            if( payType.settings.enabled === false )
            {
              continue;
            }
            else if ( payType.settings.requiresAttr )
            {
              if ( productsList.find('option[' + payType.settings.requiresAttr + ']').size() === 0 )
              {
                continue;
              }
              if ( "console" in window && console.debug )
              {
                console.debug(' >> Found required attr: ' + payType.settings.requiresAttr );
              }
            }
          }
          payTypes += '<li><input type="radio" name="vipPaymentType" id="vipPayment' + payType.id + '" '+(sel?'':'checked="checked" ')+'value="' + payType.id + '" /><label id="labelPayment' + payType.id + '" for="vipPayment' + payType.id + '">' + payType.text + ' <img alt="'+payType.text+'" src="'+IMAGE_URL+'/images/vip/'+payType.img+'" /></label></li>';
          sel = true;
        }
      }
      return '<ul id="vipPaymentTypes">' + payTypes + '</ul>';
    },
  
  transaction : 
  {
    error : 
      function( data )
      {
        if ( data.error && data.errMsg )
        {
          alert( data.errMsg );
        } else {
          alert( 'An unknown error occurred.' );
        }
        $('#vipPopup').slayDragon();
        $.dragonCurtainRemove( );
      }
  },
  
  getPopupContent :
    function( productType, vipLevel, productsList )
    {
      var content = '';
      var verbiage = VIP.productTypeVerbiage[productType];
      content += '<div id="vipContent">';
      content += '<h2>myYearbook!</h2>';
      
      if( VIP.uiComponentHelper.isVisible( 'SelectRecipientDiv', 'Credit' ) )
      {
        content += '<div id="vip-selectGR" class="vip-select"><strong>Who are you buying this for?</strong>&nbsp;&nbsp;';
        content += '<span id="vip-selectGR-text">' + VIP.util.setRecipient( null, true ) + '</span></div>';
      }
      
      content += '<div id="vip-selectPT" class="vip-select"><h3>' + verbiage.payTypeSelect + '</h3>' + VIP.getPaymentTypes( productsList ) + '</div>';
      content += '<div id="vip-selectPP" class="vip-select"><h3>' + verbiage.productSelect + '</h3></div>';
      if ( verbiage.superText )
      {
        if ( verbiage.superText.hasLevel && vipLevel )
        {
          content += '<div id="vip-superText">' . verbiage.superText.hasLevel.replace( /%levelName%/g, vipLevel ) + '</div>';
        }
        else if ( verbiage.superText.noLevel && ! vipLevel )
        {
          content += '<div id="vip-superText">' + verbiage.superText.noLevel + '</div>';
        }
      }
      if ( verbiage.cashOnly )
      {
        content += '<div id="vip-cashOnly" class="vip-select" style="display: none;">' + verbiage.cashOnly + '</div>';
      }
      content += '<button id="vip-btnContinue"> ' + productType + ' </button>';
      if ( verbiage.subText )
      {
        if( VIP.uiComponentHelper.isVisible( 'VIPSubtextDiv', 'Credit' ) )
        {
          if ( verbiage.subText.hasLevel && vipLevel )
          {
            content += '<div id="vip-subText">' + verbiage.subText.hasLevel.replace( /%levelName%/g, vipLevel ) + '</div>';
          }
          else if ( verbiage.subText.noLevel && ! vipLevel )
          {
            content += '<div id="vip-subText">' + verbiage.subText.noLevel + '</div>';
          }
        }
      }
      content += '</div>';
      return content;
    },

  popup : 
    function( productType, preselect )
    {
      if ( ! productType )
      {
        // No product type specified
        if ( "console" in window && console.warn )
        {
          console.warn( "No product type specified" );
        }
        return false;
      }
      
      $('#vipPopup').remove();
      $('.vipCompareDD, #vipPopup, #VIPPointsDragonDrop').slayDragon(null, true);
      
      VIP.productRecipient = 0;
      VIP.productType = productType;
      
      var i = 0;
      var productsList = $('select[data-product-type="' + productType + '"]');
      var verbiage = VIP.productTypeVerbiage[productType];
      if ( ! productsList.size() )
      {
        // Product list could not be found!
        if ( "console" in window && console.warn )
        {
          console.warn( "Product list for type=" + productType + " could not be found" );
        }
        var msg = 'Purchases are currently unavailable..  Please try again later!';
        if ( verbiage.maintenance )
        {
          msg = verbiage.maintenance;
        }
        $.dragonAlert( msg );
        return false;
      }

      // Get current VIP level from <select> attribute
      var vipLevel = productsList.attr('data-current-vip-level') || '';
      VIP.vipLevel = vipLevel; //XXX: clean this up
      VIP.vipModifier = ( typeof productsList.attr('data-current-vip-modifier') != 'undefined' ? productsList.attr('data-current-vip-modifier') : false );
      
      VIP.dragon( VIP.getPopupContent( productType, vipLevel, productsList ), verbiage.title );
      
      $('#friendSelectorLink').one( 'click', function() { VIP.util.friendSelector( VIP.util.friendSelectorInit ) } );
      VIP.util.dispatch( verbiage, 'onDOMAppend' );
      if ( "MyYearbook" in window )
      {
        if ( "URLs" in window.MyYearbook )
        {
          if ( window.MyYearbook.URLs.VIP )
          {
            $('a.temp-vip-url').attr('href', window.MyYearbook.URLs.VIP);
          }
        }
      }
      productsList.clone().attr('id', 'vip-products').css('visibility', 'visible').insertAfter('#vipContent #vip-selectPP h3').show();

      if ( productType == 'vip_membership' && vipLevel )
      {
        if ( $('#vip-products option:contains("' + vipLevel + '"):eq(0)').size() > 0 )
        {
          if ( preselect && preselect.toLowerCase() == vipLevel.toLowerCase() )
          {
            preselect = null;
          }
        }
      }
    
      $('#vipPopup').removeClass('loading').addClass('vip-product-' + productType);
      
      // Assign a css class based on current VIP level
      if ( vipLevel )
      {
      VIP.uiComponentHelper.toggleVIPDisabled( VIP.util.isGift(), 'Credit' );
        $('#vipPopup').addClass('vip-has-level').addClass( 'vip-level-' + vipLevel );
      }
      else
      {
        $('#vipPopup').addClass('vip-no-level');
      }
      
      $('#vip-products').bind('change.vipcb', function() {
        VIP.util.dispatch( verbiage, 'onProductChange' );
      });

      
      // IEsixsuxfixfux
      $('<select id="vip-products-ie6" style="display:none;"></select>').hide().insertAfter('#vip-products').add('#vip-products-ie6').hide();
      $('#vipPaymentTypes input:radio').bind( 'click.vip', function() {
        // Keep track of current value to make sure it gets re-selected
        var tempVal = $('#vip-products').val();
        var selList = $('#vip-products');
        var ie6List = $('#vip-products-ie6');
        
        // If options are currently hidden, add them back
        if ( ie6List.children('option').size() > 0 )
        {
          ie6List.children('option').appendTo(selList);
        }

        // Hide options that are not supported by the selected payment type
        var payType = VIP.paymentTypes[ $(this).val() ];
        
        if ( payType.settings && payType.settings.requiresAttr )
        {
          selList.children('option').filter(':not(option[' + payType.settings.requiresAttr + '])').appendTo( ie6List );
        }
        // Change selection to the previously stored value, or choose L$1M if its no longer available
        if ( ! selList.children('option[value="'+tempVal+'"]').size() )
        {
          if ( ! selList.children('option[value="9.99"]').size() )
          {
            selList.val('5');
          }
          else
          {
            selList.val('9.99');
          }
        }
        else if ( selList.val() != tempVal )
        {
          selList.val(tempVal);
        }
        VIP.util.dispatch( verbiage, 'onPaymentTypeChange' );
      });
      
      VIP.util.dispatch( verbiage, 'productListInit' );

      if ( preselect && isNaN( preselect ) )
      {
        preselect = preselect.toProperCase();
        preselect = $('#vip-products').data('productChanged', true).find('option:contains("' + preselect + '"):eq(0)').val();
      }
      else if ( ! preselect )
      {
        if ( ! $('#vip-products option[data-currency-code="USD"]').size() )
        {
          preselect = $('#vip-products option[data-currency-amount="5"]:eq(0)').val();
        }
        else
        {
          preselect = $('#vip-products option[data-currency-amount="9.99"]:eq(0)').val();
        }
      }

      if ( preselect && ! isNaN( preselect ) )
      {
        $('#vip-products').val( preselect );
      }

      $('#vip-btnContinue').bind('click.vipContinue', function() {
        var thisProductType = $('#vip-products').attr('data-product-type');
        if ( ! thisProductType )
        {
          return alert( 'An unexpected error occurred detecting product type!' );
        }
        var ptSelected = $('#vipPaymentTypes input:checked');
        var payType = VIP.paymentTypes[ ptSelected.val() ];
        if ( ptSelected.size() != 1 || ! payType )
        {
          return alert( verbiage.payTypeSelect );
        }
        var ppList = document.getElementById('vip-products');
        if ( isNaN( ppList.selectedIndex ) )
        {
          return alert( verbiage.productSelect );
        }
        var selected = ppList.options[ppList.selectedIndex];
        if ( payType.settings && payType.settings.requiresAttr && ! $(selected).attr(payType.settings.requiresAttr) )
        {
          return alert('That price selection is not available for payment via '+payType.text+'!');
        }
        
        var product = $(selected).val();
        if ( ! product )
        {
          return alert('An error was encountered trying to figure out what type of purchase you want to make.  Please make sure all items are selected properly.');
        }
        var data = { product_id: product, product_type: thisProductType, payType: ptSelected.val() };

        // If necessary, pass extra data to the start url
        if ( $(ppList).attr( 'data-vip-extra' ) )
        {
          data.extra = $(ppList).attr( 'data-vip-extra' );
        }
        
        if ( ( data.payType == 'Cash' || VIP.util.isGift() ) && data.product_type == 'vip_membership' )
        {
          data.quantity = $('#vip-quantities').val();
        }
        
        if( parseInt( VIP.productRecipient ) > 0 )
        {
          data.givenTo = parseInt( VIP.productRecipient );
        }
        
        if( ptSelected.val() == VIP.paymentTypes.AskParents.id || ptSelected.val() == VIP.paymentTypes.AskFriend.id )
        {
          if( VIP.util.validateRequestForm() !== 0 )
          {
            return false;
          }

          var recipient = false;
          if( $('#vipFriendRequestOptions :radio:checked').size() > 0 )
          {
            recipient = $('#vipFriendRequestOptions :radio:checked').val();
          }
          
          data.recipientName = $('#PRF-recipient-name').val();
          data.recipientEmail = $('#PRF-recipient-email').val();
          data.realName = $('#PRF-real-name').val();
          
          if( recipient !== false && recipient != 'Other' )
          {
            data.recipientName = recipient;
          }
        }

        // ajax to vip start, create transaction and find out what to do (zong frame, or ssl checkout)
        $('#vipPopup').addClass('loading');
        $.ajax({
          url:VIP.url + '/start', data:data, type:'post', dataType:'script', 
          error: 
            function()
            {
              $('#vipPopup').removeClass('loading'); 
            },
          complete: 
            function() 
            {
              if ( data.payType == 'Zong' )
              {
                $('#vipPopup').removeClass('loading');
              }
            } 
        });
      });
      
      VIP.uiComponentHelper.onUIChange();
    },
  
  /**
   * PayPal/Credit-specific functions
   */
  PayPal : 
  {
    transaction : 
    {
      start : 
        function ( data )
        {
          $('#vipPopup').addClass('loading');
          location.href = data.url;
        },
      error : 
        function ( data )
        {
          if ( "console" in window && console.error )
          {
            console.error(data);
          }
        }
    }
  },
  
  /**
   * Zong-specific functions
   */
  Zong : 
  {
    frameTemplate : '<iframe id="zongFrame" frameborder="0" scrolling="no" />',
    transaction : 
    {
      start : 
        function ( data )
        {
          $('#zongFrame').remove();
          $('#vipPopup').css({width:382}).find('#vipContent').empty().append( VIP.Zong.frameTemplate );
          $('#zongFrame').attr('src', data.frameUrl);
        },
      error : 
        function ( data )
        {
          if ( "console" in window && console.error )
          {
            console.error(data);
          }
        }
    }
  },
  
  Cash :
  {
    transaction :
    {
      start :
        function ( data )
        {
          $('#vipPopup').addClass('loading');
          location.href = data.url;
        },
      error :
        function( data )
        {
          if ( "console" in window && console.error )
          {
            console.error(data);
          }
        }
    }
  },
  
  CashCard :
  {
    transaction :
    {
      start :
        function ( data )
        {
          $('#vipPopup').addClass('loading');
          location.href = data.url;
        },
      error :
        function( data )
        {
          if ( "console" in window && console.error )
          {
            console.error(data);
          }
        }
    }
  },
  
  AskParents :
  {
    transaction :
    {
      start :
        function ( data )
        {
          VIP.requestSentDragon();
        },
      error :
        function( data )
        {
          if ( "console" in window && console.error )
          {
            console.error(data);
          }
          
          if ( data.error && data.errMsg )
          {
            $('#vipPopup').removeClass('loading')
            alert( data.errMsg );
          }
          else
          {
            VIP.transaction.error( data );
          }
        }
    }
  },
  
  AskFriend :
  {
    transaction :
    {
      start :
        function ( data )
        {
          VIP.requestSentDragon();
        },
      error :
        function( data )
        {
          if ( "console" in window && console.error )
          {
            console.error(data);
          }
          
          if ( data.error && data.errMsg )
          {
            $('#vipPopup').removeClass('loading')
            alert( data.errMsg );
          }
          else
          {
            VIP.transaction.error( data );
          }
        }
    }
  },
  
  dragon : function( content, title )
  {
    $('<div id="vipPopup" class="loading" />')
      // Append to body first so that DD takes body's position:relative into account for initial placement
      .appendTo('body')
      .dragonDrop({
        "type": 'window',
        "title": title,
        "centerOnScreen": true,
        "enableMinMax": false,
        "enableClose": true,
        // "enableCloseEsc": true, //XXX: Breaks curtain
        "curtain": true,
        "width": 392,
        "height": 282,
        "content": content
      });
      // Re-append to body to fix a bug in IE7 with background-image styles breaking
      if ( jQuery.browser.msie )
      {
        $('#vipPopup').appendTo('body');
      }
    $('#vipPopup').addClass('activeDragon');
    $('#vipPopup').removeClass('activeDragon');
  },
  
  friendSelectorDragon : function( content, title )
  {
    $('<div id="vipFriendSelector" class="loading" />')
      // Append to body first so that DD takes body's position:relative into account for initial placement
      .appendTo('body')
      .dragonDrop({
        "type": 'window',
        "title": title,
        "centerOnScreen": true,
        "enableMinMax": false,
        "enableClose": true,
        // "enableCloseEsc": true, //XXX: Breaks curtain
        "curtain": false,
        "width": 600,
        "height": 520,
        "content": content,
        "callbackClose": function() { $('#friendSelectorLink').one( 'click', function() { VIP.util.friendSelector( VIP.util.friendSelectorInit ) } ) }
      });
      // Re-append to body to fix a bug in IE7 with background-image styles breaking
      if ( jQuery.browser.msie )
      {
        $('#vipFriendSelector').appendTo('body');
      }
    $('#vipFriendSelector').addClass('activeDragon');
    $('#vipFriendSelector').removeClass('activeDragon');
  },
  
  requestSentDragon: function()
  {
    var content = '';
    content += '<div id="vipContent">';
    content += '<h2>myYearbook!</h2>';
    
    content += '<div class="vip-select">';
    content += '<h3>' + VIP.productTypeVerbiage[ VIP.productType ].friendSelect + ' Request Sent!</h3>';
    
    content += '<div id="vip-request-email">An email has been sent to:<br/>';
    content += '<strong>' + $('#PRF-recipient-email').val() + '</strong></div>';
    
    
    content += '<div>Please tell them to check this email account<br/>and follow the instructions within the email.</div>';
    
    content += '</div>';
    
    content += '<div><button id="vip-btnClose"/></div>';

    $('.vipCompareDD, #vipPopup, #VIPPointsDragonDrop').slayDragon();
    $('<div id="vipRequestSent" class="loading" />')
    // Append to body first so that DD takes body's position:relative into account for initial placement
    .appendTo('body')
    .dragonDrop({
      "type": 'window',
      "title": VIP.productTypeVerbiage[ VIP.productType ].title ,
      "centerOnScreen": true,
      "enableMinMax": false,
      "enableClose": true,
      // "enableCloseEsc": true, //XXX: Breaks curtain
      "curtain": true,
      "width": 392,
      "height": 282,
      "content": content
    });
    // Re-append to body to fix a bug in IE7 with background-image styles breaking
    if ( jQuery.browser.msie )
    {
      $('#vipRequestSent').appendTo('body');
    }
    
    $('#vip-btnClose').bind('click.vipContinue', function() {
      $('#vipRequestSent').slayDragon( null, true );
    });
    
    $('#vipRequestSent').addClass('activeDragon');
    $('#vipRequestSent').removeClass('activeDragon');
    
    $('#vipRequestSent').removeClass('loading').addClass('vip-product-' + VIP.productType);
  },
  
  /**
   * These are some utility functions that are used throughout various popups
   */
  util : 
  {      
    /**
     * Generate the text/links used in the Who are you buying this for
     * box.
     */
    setRecipient :
      function( friendId, updateUI )
      {
      /**
       * When setting a new recipient default to the current user buying
       * for themselves and allow recurring payments.
       */
      VIP.productRecipient = 0;
      VIP.recurringPayments = 1;
      var recipientText = '';

      if( friendId == null )
      {
        if( typeof VIP.vipData != 'object' && VIP.vipData === false )
        {
          if( window.vipData )
          {
            VIP.vipData = window.vipData;
          }
          else
          { 
            VIP.vipData = null; 
          }
        }    

        //If this is the first load, check the popup is on a profile page
        if( VIP.vipData != null && VIP.vipData.userid != VIP.vipData.sessuserid )
        {
          VIP.productRecipient = parseInt( VIP.vipData.userid );
          VIP.recurringPayments = 0;

          friend = VIP.vipData.name;
          if( friend.length > 28 )
          {
            recipientText += friend.substring( 0, 28 );  
          }
          else
          {
            recipientText += friend;  
          }

          //Clear out the VIP data so it doesn't prepopulate on the next popup
          VIP.vipData = false;
        }
        else
        {
          if( UserSelector.noUsers === true )
          {
            recipientText += 'Myself'; 
          }
          else
          {
            recipientText += 'Myself (';
            recipientText += '<a href="javascript:void(0);" id="friendSelectorLink">Select a Friend</a>';
            recipientText += ')';
          }
        }
      }
      else
      {
        //Handle userIds from the UserSelector
        var friend = $('#UserSelector .' + friendId + '.friend .name').html();
        VIP.productRecipient = parseInt( friendId.substring( 1 ) );
        VIP.recurringPayments = 0;

        if( friend.length > 15 )
        {
          recipientText += friend.substring( 0, 15 );  
        }
        else
        {
          recipientText += friend;  
        }

        recipientText += ' (<a href="javascript:void(0);" onclick="VIP.util.selectMyself();">Myself</a>';
        recipientText += ' | <a href="javascript:void(0);" id="friendSelectorLink">A Friend</a>)';
      }
  
      if( updateUI === true )
      {
        VIP.uiComponentHelper.onUIChange();
      }

      return recipientText;
    },
    
    friendSelector :
      function( initCallback )
      {  
        var config = {};
        var data = { productType: VIP.productType };

        //Only load the config values the first time
        config.ajaxUrls = {
          init: {
            url: VIP.url + '/friendselector/friends'
          },
          pagination: {
            url: VIP.url + '/friendselector/friendspage',
            postData: data
          }
        };
        
        if( UserSelector.ajaxUrls == null )
        {
          config.messages = {
            noUsers: 'You don\'t have any friends selected.',
            maxUsers: 'You\'ve selected the maximum number of friends allowed.',
            noSearchMatches: 'None of your friends match the search term'
          };
          config.callbacks = {
            click: { 'SelectFriend':VIP.util.selectFriend, 'ResetState':UserSelector.reset },
            unselectedUserClick: UserSelector.deselectUsers,
            onPageChange: VIP.util.createVIPIcons
          };
        }
        
        UserSelector.initialize( config, data, initCallback );
      },
  
    friendSelectorInit : 
      function( data )
      {
        if( data.content === false )
        {
          //XXX:move this to util.messagePopup()
          $('#aiResultBox').remove();
          $('body').append('<div id="aiResultBox" style="padding:0px;display: none; overflow:auto;"></div>');
          $('#aiResultBox')
            .css('width', '300px' )
            .css('padding', '5px' )
            .css('font-weight','bold')
            .html('<span style="float:left;">You have no friends!</div><div id="aiResultMessage" style="display: none;"></div><div id="aiResultClose"><img alt="Close" src="' + IMAGE_URL + '/updateicons/notifications_x.gif"></div>')
            .centerOnScreen().fadeIn();

          $('#aiResultClose')
            .click(function() { 
              $('#aiResultBox').remove();                     
              $.dragonCurtainRemove();
              return false; 
            });
    
          if(window.location==top.location)
          {
            $.dragonCurtain();
          }
        }
        else
        {
          VIP.friendSelectorDragon( data.content, 'Select a friend to buy ' + VIP.productTypeVerbiage[VIP.productType].friendSelect + ' for...' );
          VIP.util.createVIPIcons();
          $('#vipPopup').removeClass('loading');   
          UserSelector.start();
        }
      },
  
    createVIPIcons :
      function()
      {
        $('#UserSelector .content.all .friend').each(function(){
          var userid = $(this).find('.id.hidden').text();
          var vipLevel = $(this).find('.vipLevel.hidden').text();
          if( vipLevel != '0' )
          { 
            $(this).find('.actionIcons.u' + userid).addClass('largeActionIcon').addClass('btnActionIcon').addClass('aiIconPopUp').addClass('VIP' + vipLevel);
          }
        });  
      },
    
    hasRecurringVIP :
      function()
      {
        var selectedUser = '';
        $.each(UserSelector.cleanState.selectedFriends,function(i,v){
          selectedUser = i;
        });
        
        if( parseInt( $('div.content.selected div.friend.' + selectedUser, '#UserSelector' ).attr( 'data-has-recurring-vip' ) ) == 1 )
        {
          return true;
        }
        
        return false;
      },
  
    selectFriend :
      function()
      {
        if ( UserSelector.selectedCount == 0 )
        {
          UserSelector.displayError( 'You must select a friend to buy ' + VIP.productTypeVerbiage[VIP.productType].friendSelect + ' for.', 3000 );
          return false;
        }
        else if ( VIP.util.hasRecurringVIP() )
        {
          UserSelector.deselectUsers();
          UserSelector.reset();
          UserSelector.displayError( 'You cannot gift VIP Access to this user.', 3000 );
          return false;
        }

        //Find a better way to do this
        var friendId = '';
        $.each(UserSelector.cleanState.selectedFriends,function(i,v){
          friendId = i;
        });

        $('#vip-selectGR-text').html( VIP.util.setRecipient( friendId, true ) );
        $('#vipFriendSelector').slayDragon();
        $('#friendSelectorLink').one( 'click', function() { VIP.util.friendSelector( VIP.util.friendSelectorInit ) } );
      },
    
    selectMyself :
      function()
      {
        $('#vip-selectGR-text').html( VIP.util.setRecipient( null, true ) );
        $('#friendSelectorLink').one( 'click', function() { VIP.util.friendSelector( VIP.util.friendSelectorInit ) } );
      },
    
    isGift :
      function()
      {
        if( parseInt( VIP.productRecipient ) > 0 )
        {
          return true;
        }

        return false;
      },
    
    //XXX:This function might not be necessary anymore
    recurringPaymentsAllowed :
      function()
      {
        var isCash = $('#vipPaymentTypes input:checked').val() == 'Cash';

        if( !isCash && !VIP.util.isGift() )
        {
          return true;
        }

        return false;
      },
      
    validateRequestForm :
      function( )
      {
        $("#vipPopupGiftRequestForm").validate().form();
        return $("#vipPopupGiftRequestForm").validate().numberOfInvalids();
      },
     
    initPrices :
      function( )
      {
        var $productList = $('#vip-products');
        var originalPrices = {};
        var roundPrices = {};
        var usdPrices = {};
        var originalText = {};
        $productList.children('option').each( function() {
          var key = '_' + this.value;
          var symbol = '';
          switch( $(this).attr('data-currency-code') )
          {
            case 'USD':
              symbol = '$';
              break;
            case 'GBP':
              symbol = '\u00A3';
              break;
          }
          originalPrices[ key ] = parseFloat( $(this).attr('data-currency-amount' ) ).toFixed(2);
          if ( $(this).attr('data-rounded-usd-price') )
          {
            usdPrices[ key ] = { "usd": '$' + parseFloat( $(this).attr('data-rounded-usd-price' ) ).toFixed(2), "original" : symbol + originalPrices[ key ] };
          }
          roundPrices[ key ] = Math.round( originalPrices[ key ] ).toFixed(2);
          originalText[ key ] = $(this).text();
        });
        $productList.data( 'originalPrices', originalPrices ).data( 'roundPrices', roundPrices ).data( 'usdPrices', usdPrices ).data('originalText', originalText );
      },
    
    updateProducts : 
      function( payment )
      {
        var $productList = $('#vip-products');
        var originalPrices = $productList.data( 'originalPrices' );
        var roundedPrices = $productList.data( 'roundPrices' );
        var usdPrices = $productList.data( 'usdPrices' );
        var originalText = $productList.data( 'originalText' );

        $productList.data( 'isTrial', payment.settings.allowsTrial );
        
        var symbol = $productList.attr('data-currency') === 'USD' ? '$' : '\u00A3';
        
        if ( payment.settings.roundsPrices )
        {
          if ( "console" in window && console.debug )
          {
            console.debug( ' >> Rounding prices' );
          }
          $('#freeTrialSubText').hide();
          var toList = roundedPrices;
          if ( $productList.attr('data-currency') != 'USD' )
          {
            // If not USD, we have to replace original price (with currency symbol included) to a rounded USD price (with '$')
            toList = usdPrices;
          }
          $productList.find('option').each(function(){
            var key = '_' + this.value;
            var s = toList[ key ].usd ? toList[ key ].original : originalPrices[ key ];
            var r = toList[ key ].usd ? toList[ key ].usd : roundedPrices[ key ];
            var t = originalText[ key ].replace( s, r );
            $(this).text( t );
          });
        }
      },

    /**
     * Confirm product-to-payment-type requirements
     * If a product is selected that does not meet those requirements, unchecks the payment type.
     */
    checkPaymentProduct : 
      function( )
      {
        var list = $('#vip-products').get(0);
        var selected = list.options[list.selectedIndex];
        var payType = VIP.paymentTypes[ $('#vipPaymentTypes input:checked').val() ];
        if ( ! payType || ! payType.settings || ! payType.settings.requiresAttr )
        {
          return;
        }
        if ( ! $(selected).attr(payType.settings.requiresAttr) )
        {
          $('#vipPayment' + payType.id).attr('checked', '');
        }
      },
    
    /**
     * Called when changing payment method.
     * Alters price lists to round price to the nearest dollar amount.
     */
    cashPaymentChange :
      function()
      {
        VIP.util.cashProductChange( true );
        var $productList = $('#vip-products');
        var isCash = $('#vipPaymentTypes input:checked').val() == 'Cash';

        if ( isCash )
        {
          $productList.children('option:disabled').each(function(){
            $(this).data('wasDisabled', true).attr('disabled','');
            if ( ! $productList.data( 'productChanged' ) )
            {
              $productList.val( $(this).val() );
            }
          });
        }
        else
        {
          $productList.children('option').each(function(){
            if ( $(this).data('wasDisabled') )
            {
              $(this).attr('disabled', 'disabled' );
              if ( $productList.val() == $(this).val() )
              {
                $productList.val( $(this).siblings('option:last').val() );
              }
            }
          });
        }
      },

    cashProductChange :
      function( autoTrigger )
      {
        var $products = $('#vip-products');
        var $this = $('#vip-quantities');
        var $selected = $products.find('option:selected');
        var curSymbol = $products.attr('data-currency') == 'USD' ? '$' : '\u00A3';
        var unitPrice = parseFloat( $selected.attr('data-currency-amount') );

        if( VIP.paymentTypes[ $('#vipPaymentTypes input:checked').val() ].settings.roundsPrices !== true )
        {
          var original = $products.data( 'originalPrices' );
          if ( original )
          {
            unitPrice = parseFloat( original[ '_' + $selected.val() ] );  
          }
        }
        else
        {
          var rounded = $products.data( 'roundPrices' );
          if ( rounded )
          {
            unitPrice = parseFloat( rounded[ '_' + $selected.val() ] );
          }
        }
         
        if ( ! autoTrigger )
        {
          $products.data( 'productChanged', true );
        }

        $this.find('option').each( function() {
          var totalPrice = parseFloat( $(this).val() ) * unitPrice;
          var t = $(this).text();
          t = t.replace(/ \(.*$/, '');
          t += ' (' + curSymbol + totalPrice.toFixed(2) + ')';
          $(this).text( t );
        });
      },
    
    vipZongDisclaimer :
      function()
      {
        var payType = $('#vipPaymentTypes input:checked').val();
        if ( payType === VIP.paymentTypes.Zong.id )
        {
          if ( $('span.vip-downgrading:visible', '#vip-subText').size() > 0 )
          {
            $('span.vip-downgrading,span.vip-downgrading-zongOnly', '#vip-subText').show();
          }
        }
        else if ( $('span.vip-downgrading-zongOnly:visible', '#vip-subText').size() > 0 )
        {
          $('span.vip-downgrading-zongOnly', '#vip-subText').hide();
        }
      },
    
    popupDriver :
      function( e )
      {
        var productType = $(this).attr('data-vip-product-type') || false;
        var preselect = $(this).attr('data-vip-preselect') || '';
        
        if( VIP.assetsLoaded !== 'loaded' && VIP.isGiftingEnabled === true )
        {
          productBootloader( productType, null, preselect );
          return false;
        }
        
        if ( $(this).hasClass('vip-driver-loading') )
        {
          return true;
        }
        //var productType = $(this).attr('data-vip-product-type') || false;
        //var preselect = $(this).attr('data-vip-preselect') || '';
        if ( ! productType )
        {
          if ( "console" in window && console.warn )
          {
            console.warn('no data-vip-product-type attr');
          }
          return true;
        }

        VIP.popup( productType, preselect );
        return false;
      },

    /** 
     * Sets up free trial content in purchase popup
     */
    initializeFreeTrial : 
      function( subText, trialLength )
      {
        VIP.productTypeVerbiage.vip_membership.subText.noLevel = subText;
        var sel = $('select[@data-product-type="vip_membership"]');
        if ( sel.attr( 'data-current-vip-level' ) )
        {
          return false;
        }
        sel.attr( 'data-vip-extra', 'trial' );
      },
    
    dispatch :
      function( settings, callbackType )
      {
        if ( ! settings || ! callbackType )
        {
          return false;
        }
        if ( ! settings.callbacks )
        {
          return false;
        }
        var cb = settings.callbacks[ callbackType ];
        if ( typeof cb != 'function' )
        {
          return false;
        }
        if ( "console" in window && console.debug )
        {
          console.debug( ' > Dispatching callback: ', callbackType );
        }
        cb( settings );
      }
  },

  convertNote : function( )
  {
    if ( ! $('.convertNote').size() )
    {
      $('<div id="VIPNoteDragonDrop" class="convertNote" />').appendTo('body').dragonDrop({
        title : 'VIP Points Converted to L$',
        content : '<div>Based on feedback from members, we decided to remove VIP Points and exchange every 1 VIP Point for L$2000 Lunch Money.<br/><br/>' + 'In addition, we made VIP Gifts - the only thing that could previously be purchased with VIP Points - free to VIPs, up to 30 per day</div>' + '<a href="#" onclick="$(\'#VIPNoteDragonDrop\').slayDragon(); return false;" class="normaltextlink">Close<a/>',
        draggable: false,
        enableClose : true,
        enableMinMax : false,
        curtain : false,
        type : 'window'
      });
    }
    return false;
  }
};

function loadVIPUrl()
{
  if ( VIP.url == null )
  {
    if ( window.SERVICE_NAME )
    {
      VIP.url = BASE_URL + 'vip/ajax';
    } 
    else
    {
      VIP.url = SITE_URL + 'apps/vip/ajax';
    }
  }
}

function loadAge()
{
  if ( VIP.age == null )
  {
    if( "age" in window )
    {
      setAge( window.age );
    }
    else
    {
      $.ajax({
        type:'get',
        dataType:'json',
        url:VIP.url + '/userage',
        success:function(data)
        {
          setAge( data.age );
        }
      });
    }
  }
}

function setAge( age )
{
  VIP.age = age; 
  if( typeof age == 'undefined' || parseInt( age ) < 18 )
  {
    VIP.paymentTypes.AskParents.settings.enabled = true;
  }
  else
  {
    VIP.paymentTypes.AskFriend.settings.enabled = true;
  }
}

function initFriendSelector( productType, preselect )
{
  if ( VIP.friendSelectorLoaded != 'complete' )
  {
    // Probably will need check to determine if this is really first friends load.... 
    loadAge();

    var jQUrl = jQuery.fn.jquery && '-' + jQuery.fn.jquery;
    MyYearbook.BootLoader.add( IMAGE_URL + '/JavaScript/apps/jQuery' + jQUrl + '/Plugins/jquery-validator/jquery.validate.js' );
    MyYearbook.BootLoader.add( IMAGE_URL + '/css/apps/Pagination/Paginator.css', 'css' );
    MyYearbook.BootLoader.add( IMAGE_URL + '/css/apps/UserSelector/UserSelector.css', 'css' );
    MyYearbook.BootLoader.add( IMAGE_URL + '/JavaScript/apps/Pagination/Paginator.js' );
    $.getScript( IMAGE_URL + '/JavaScript/apps/UserSelector/UserSelector.js', function() {
      VIP.util.friendSelector( function() { 
        VIP.friendSelectorLoaded = 'complete';
        VIP.popup( productType, preselect ); 
        $('.vip-driver-loading').removeClass('loading').removeClass('vip-driver-loading');
      });
    });
  }
  else
  {
    VIP.util.friendSelector( function() { 
      VIP.popup( productType, preselect ); 
      $('.vip-driver-loading').removeClass('loading').removeClass('vip-driver-loading');
    });
  }
}

/**
 * userData
 *  .userid
 *  .firstName
 *  .lastName
 * 
 * @param productType
 * @param userData
 * @return
 */
function productBootloader( productType, userData, preselect )
{
  loadVIPUrl();

  $productsList = $('select[data-product-type="lunchmoney"],select[data-product-type="vip_membership"]');
  if( $productsList.size() < 2 )
  {
    $('.vip-driver-loading').addClass('loading').unbind('click.viploading');
    
    $.ajax({
      type:'get',
      dataType:'json',
      async: false,
      url:VIP.url + '/prices',
      success:function(data)
      {
        if ( data.markup === false )
        {
          $('.vip-popup-driver').unbind('click.vip').removeClass('vip-popup-driver').addClass('vip-driver-fail');
          $('#buyLM button:eq(0)').after('<div style="float: right; margin-top: 5px; color: #900; font-weight: bold; padding: 5px 15px;">Temporarily Unavailable</div>');
          $('#buyLM button').remove();
          return;
        }
        // Keep track of VIP Trial note when replacing the vip_membership product list
        var extra = $('select[data-product-type="vip_membership"]').attr('data-vip-extra');
        $productsList.remove();
        $('body').append( data.markup );
        if ( extra != '' )
        {
          // So we can readd it here.
          $('select[data-product-type="vip_membership"]').attr('data-vip-extra', extra);
        }
        
        productBootloader( productType, userData, preselect );
      }
    });
  }
  else
  {
    //information wasn't passed, go grab it
    if( userData != null && parseInt( userData.userid ) > 0 )
    {
      $.ajax({
        type:'get',
        data: { userid:userData.userid, type:productType },
        dataType:'json',
        url:VIP.url + '/cangift',
        async: false,
        success:function(data)
        {
          if( data.cangift == false )
          {
            //XXX: display a message & close the curtain
            $('#aiResultBox').remove();
            $('body').append('<div id="aiResultBox" style="padding:0px;display: none; overflow:auto;"></div>');
            $('#aiResultBox')
              .css('width', '300px' )
              .css('padding', '5px' )
              .css('font-weight','bold')
              .html('<span style="float:left;">' + unescape(data.error) + 
                    '</span><div id="aiResultMessage" style="display: none;"></div><div id="aiResultClose"><img alt="Close" src="' + IMAGE_URL + 
                    '/updateicons/notifications_x.gif"></div>')
              .centerOnScreen().fadeIn();
          
            $('#aiResultClose')
              .click(function() { 
                $('#aiResultBox').remove();                     
                $.dragonCurtainRemove();
                return false; 
              });
          
            if(window.location==top.location)
            {
              $.dragonCurtain();
            }
          }
          else if( data.isself !== true )
          {
            VIP.vipData = { userid:data.userdata.userid, sessuserid:null, name:data.userdata.firstName + ' ' + data.userdata.lastName };
            VIP.popup( productType );
          }
          else
          {
            initFriendSelector( productType, preselect );
          }
        }
      });
    }
    else  // We assume you are gifting yourself.
    {
      initFriendSelector( productType, preselect );
    }
  }
}

$(document).ready(function(){
  if ( VIP.isGiftingEnabled === false )
  {
    UserSelector = { "noUsers" : true };
  }
  
  /** Main VIP popup driver **/
  $('.vip-popup-driver').bind( 'click.vip', VIP.util.popupDriver );
  
  if ( location.hash.indexOf( 'vip-popup=' ) != -1 )
  {
    setTimeout( function(){
      var productType = location.hash.substring( location.hash.indexOf( 'vip-popup=' ) + 10 );
      $('.vip-popup-driver[data-vip-product-type="'+productType+'"]:eq(0)').triggerHandler('click.vip');
    }, 300 );
  }

  //VIP Points Question Mark Popup
  $('a.vipQuestionMark').click( function(e) {
    if ( ! $('.vipPointsDD').size() )
    {
      $('<div id="VIPPointsDragonDrop" class="vipPointsDD" />').appendTo('body').dragonDrop({
        title : 'What are VIP Points?',
        left : e.pageX - $.getBodyMarginLeft(),
        top: e.pageY - 65,
        content : 'You can use VIP Points to buy special, highly customizable VIP Gifts that are placed front and center for everyone to see on the profile. VIP Club members get up to 2000 VIP Points free every month with their subscription.<br/><br/><a href="#" onclick="$(\'#VIPPointsDragonDrop\').slayDragon(); return false;" class="closeLink">Close<a/>',
        draggable: false,
        enableClose : true,
        enableMinMax : false,
        curtain : false,
        type : 'window'
      });
    }
    return false;
  });

  var imageCount = 4;
  var rand = Math.floor( Math.random() *  imageCount ) + 1;
  $('#whyJoin').attr( 'index', rand ).css('background', 'url(' + IMAGE_URL + '/images/vip/vip_module' + rand + '.png)');
  $('div.nav').click( function() {
    var currentReason = $('#whyJoin').attr('index') - 0; 
    if ( $(this).attr('id') == 'next' ) {
 
      if ( currentReason != imageCount )
      {
        nextReason = currentReason + 1;
      }
      else
      { 
        nextReason = 1;
      }
      newReason = nextReason;
  
   } else 
   {
     if ( currentReason != 1 )
     {
       prevReason = currentReason - 1;
     }
     else
     {
       prevReason = imageCount;
     }
     newReason = prevReason;
   }
   $('#whyJoin').attr( 'index', newReason ).css('background', 'url(' + IMAGE_URL + '/images/vip/vip_module' + newReason + '.png)');

  });
});
String.prototype.toProperCase = function(){
  return this.toLowerCase().replace(/\w+/g,function(s){
    return s.charAt(0).toUpperCase() + s.substr(1);
  });
};
