(function(context,$) {

  "use strict";
  context.JK = context.JK || {};
  context.JK.CheckoutPaymentScreen = function(app) {

    var EVENTS = context.JK.EVENTS;
    var logger = context.JK.logger;
    var jamTrackUtils = context.JK.JamTrackUtils;
    var checkoutUtils = context.JK.CheckoutUtilsInstance;

    var $screen = null;
    var $navigation = null;
    var $billingInfo = null;
    var $shippingInfo = null;
    var $paymentMethod = null;
    var $shippingAddress = null;
    var $shippingAsBilling = null;
    var $paymentInfoPanel = null;
    var $accountSignup = null;
    var userDetail = null;
    var step = null;
    var billing_info = null;
    var shipping_info = null;
    var shipping_as_billing = null;
    var $reuseExistingCard = null;
    var $reuseExistingCardChk = null;
    var $existingCardEndsWith = null;
    var $newCardInfo = null;
    var selectCountry = null;
    var selectCountryLoaded = false;
    var $freeJamTrackPrompt = null;
    var $noFreeJamTrackPrompt = null;
    var $alreadyEnteredJamTrackPrompt = null;

    function afterShow() {

      beforeShowPaymentInfo();
    }

    function beforeShowPaymentInfo() {
      step = 2;
      renderNavigation();
      renderAccountInfo();
    }


    function renderAccountInfo() {

      $paymentInfoPanel.addClass('hidden')
      $reuseExistingCard.addClass('hidden');
      $newCardInfo.removeClass('hidden');
      $freeJamTrackPrompt.addClass('hidden');
      $noFreeJamTrackPrompt.addClass('hidden');
      $alreadyEnteredJamTrackPrompt.addClass('hidden')
      $("#payment_error").addClass('hidden').text('')


      if(checkoutUtils.shouldPreserveBillingInfo()) {
        logger.debug("showing 'user has already set up billing info' because 'preserve billing' session is active")
        checkoutUtils.refreshPreserveBillingInfo()
        $alreadyEnteredJamTrackPrompt.removeClass('hidden')
        return
      }

      $paymentInfoPanel.removeClass('hidden')


      var selectCountryReady = selectCountry.ready();
      if(!selectCountryReady) {
        // one time init of country dropdown
        selectCountryReady = selectCountry.load('US', null, null);
      }

      selectCountryReady.done(function() {
        var user = rest.getUserDetail()
        if(user) {
          user.done(populateAccountInfo).error(app.ajaxError);
        }
        else {
          $reuseExistingCardChk.iCheck('uncheck').attr('checked', false)
          if(gon.global.one_free_jamtrack_per_user) {
            $freeJamTrackPrompt.removeClass('hidden')
          }
          else {
            $noFreeJamTrackPrompt.removeClass('hidden')
          }
        }
      })
    }

    function populateAccountInfo(user) {
      userDetail = user;

      $reuseExistingCardChk.iCheck(userDetail.reuse_card && userDetail.has_recurly_account ? 'check' : 'uncheck').attr('checked', userDetail.reuse_card)

      // show appropriate prompt text based on whether user has a free jamtrack
      if(user.has_redeemable_jamtrack) {
        $freeJamTrackPrompt.removeClass('hidden')
      }
      else {
        $noFreeJamTrackPrompt.removeClass('hidden')
      }

      if (userDetail.has_recurly_account) {

        rest.getBillingInfo()
          .done(function(response) {

            if(userDetail.reuse_card) {
              $reuseExistingCard.removeClass('hidden');
              toggleReuseExistingCard.call($reuseExistingCardChk)
              $existingCardEndsWith.text(response.billing_info.last_four);
            }

            var isSameAsShipping = true // jamTrackUtils.compareAddress(response.billing_info, response.address);

            $shippingAsBilling.iCheck(isSameAsShipping ? 'check' : 'uncheck').attr('checked', isSameAsShipping)

            $billingInfo.find("#billing-first-name").val(response.billing_info.first_name);
            $billingInfo.find("#billing-last-name").val(response.billing_info.last_name);
            $billingInfo.find("#billing-address1").val(response.billing_info.address1);
            $billingInfo.find("#billing-address2").val(response.billing_info.address2);
            $billingInfo.find("#billing-city").val(response.billing_info.city);
            $billingInfo.find("#billing-state").val(response.billing_info.state);
            $billingInfo.find("#billing-zip").val(response.billing_info.zip);
            $billingInfo.find("#billing-country").val(response.billing_info.country);

            //$shippingAddress.find("#shipping-first-name").val(response.billing_info.first_name);
            //$shippingAddress.find("#shipping-last-name").val(response.billing_info.last_name);
            //$shippingAddress.find("#shipping-address1").val(response.address.address1);
            //$shippingAddress.find("#shipping-address2").val(response.address.address2);
            //$shippingAddress.find("#shipping-city").val(response.address.city);
            //$shippingAddress.find("#shipping-state").val(response.address.state);
            //$shippingAddress.find("#shipping-zip").val(response.address.zip);
            //$shippingAddress.find("#shipping-country").val(response.address.country);

          })
          .error(app.ajaxError);
      }
      else {
        $billingInfo.find("#billing-first-name").val(userDetail.first_name);
        $billingInfo.find("#billing-last-name").val(userDetail.last_name);
        $billingInfo.find("#billing-city").val(userDetail.city);
        $billingInfo.find("#billing-state").val(userDetail.state);
        $billingInfo.find("#billing-country").val(userDetail.country);

        $shippingAddress.find("#shipping-first-name").val(userDetail.first_name);
        $shippingAddress.find("#shipping-last-name").val(userDetail.last_name);
        $shippingAddress.find("#shipping-city").val(userDetail.city);
        $shippingAddress.find("#shipping-state").val(userDetail.state);
        $shippingAddress.find("#shipping-country").val(userDetail.country);
      }
    }

    function beforeShow(data) {
    }

    function beforeHide() {

    }

    function beforeHide() {

    }

    // TODO: Refactor: this function is long and fraught with many return points.
    function next(e) {

      // check if we are showing the 'change payment info' pass; if so, just move on to checkoutOrder
      if($alreadyEnteredJamTrackPrompt.is(':visible')) {
        logger.debug("skipping payment logic ")
        context.location = '/client#/checkoutOrder'
        return false;
      }
      $paymentInfoPanel.find('.error-text').remove();
      $paymentInfoPanel.find('.error').removeClass('error');
      e.preventDefault();
      $("#payment_error").addClass("hidden").text('')

      var reuse_card_this_time = $reuseExistingCardChk.is(':checked');
      var reuse_card_next_time = $paymentMethod.find('#save-card').is(':checked');

      // validation
      var billing_first_name = $billingInfo.find("#billing-first-name").val();
      var billing_last_name = $billingInfo.find("#billing-last-name").val();
      var billing_address1 = $billingInfo.find("#billing-address1").val();
      var billing_address2 = $billingInfo.find("#billing-address2").val();
      var billing_city = $billingInfo.find("#billing-city").val();
      var billing_state = $billingInfo.find("#billing-state").val();
      var billing_zip = $billingInfo.find("#billing-zip").val();
      var billing_country = $billingInfo.find("#billing-country").val();

      var billingInfoValid = true;
      if (!billing_first_name) {
        $billingInfo.find('#divBillingFirstName .error-text').remove();
        $billingInfo.find('#divBillingFirstName').addClass("error").addClass("transparent");
        $billingInfo.find('#billing-first-name').after("<ul class='error-text'><li>First Name is required</li></ul>");

        logger.info("no billing first name");
        billingInfoValid = false;
      }
      else {
        $billingInfo.find('#divBillingFirstName').removeClass("error");
      }

      if (!billing_last_name) {
        $billingInfo.find('#divBillingLastName .error-text').remove();
        $billingInfo.find('#divBillingLastName').addClass("error").addClass("transparent");
        $billingInfo.find('#billing-last-name').after("<ul class='error-text'><li>Last Name is required</li></ul>");

        logger.info("no billing last name");
        billingInfoValid = false;
      }
      else {
        $billingInfo.find('#divBillingLastName').removeClass("error");
      }

      if (!billing_address1) {
        $billingInfo.find('#divBillingAddress1 .error-text').remove();
        $billingInfo.find('#divBillingAddress1').addClass("error").addClass("transparent");
        $billingInfo.find('#billing-address1').after("<ul class='error-text'><li>Address is required</li></ul>");

        logger.info("no billing address line 1");
        billingInfoValid = false;
      }
      else {
        $billingInfo.find('#divBillingAddress1').removeClass("error");
      }

      if (!billing_zip) {
        $billingInfo.find('#divBillingZip .error-text').remove();
        $billingInfo.find('#divBillingZip').addClass("error").addClass("transparent");
        $billingInfo.find('#billing-zip').after("<ul class='error-text'><li>Zip Code is required</li></ul>");

        logger.info("no billing zip");
        billingInfoValid = false;
      }
      else {
        $billingInfo.find('#divBillingZip').removeClass("error");
      }

      if (!billing_state) {
        $billingInfo.find('#divBillingState .error-text').remove();
        $billingInfo.find('#divBillingState').addClass("error").addClass("transparent");
        $billingInfo.find('#billing-state').after("<ul class='error-text'><li>State is required</li></ul>");

        logger.info("no billing state");
        billingInfoValid = false;
      }
      else {
        $billingInfo.find('#divBillingState').removeClass("error");
      }

      if (!billing_city) {
        $billingInfo.find('#divBillingCity .error-text').remove();
        $billingInfo.find('#divBillingCity').addClass("error").addClass("transparent");
        $billingInfo.find('#billing-city').after("<ul class='error-text'><li>City is required</li></ul>");

        logger.info("no billing city");
        billingInfoValid = false;
      }
      else {
        $billingInfo.find('#divBillingCity').removeClass("error");
      }

      if (!billing_country) {
        $billingInfo.find('#divBillingCountry .error-text').remove();
        $billingInfo.find('#divBillingCountry').addClass("error").addClass("transparent");
        $billingInfo.find('#billing-country').after("<ul class='error-text'><li>Country is required</li></ul>");

        logger.info("no billing country");
        billingInfoValid = false;
      }
      else {
        $billingInfo.find('#divBillingCountry').removeClass("error");
      }

      /**
      shipping_as_billing = $shippingAsBilling.is(":checked");
      var shipping_first_name, shipping_last_name, shipping_address1, shipping_address2;
      var shipping_city, shipping_state, shipping_zip, shipping_country;

      if (!shipping_as_billing) {
        shipping_first_name = $shippingAddress.find("#shipping-first-name").val();
        shipping_last_name = $shippingAddress.find("#shipping-last-name").val();
        shipping_address1 = $shippingAddress.find("#shipping-address1").val();
        shipping_address2 = $shippingAddress.find("#shipping-address2").val();
        shipping_city = $shippingAddress.find("#shipping-city").val();
        shipping_state = $shippingAddress.find("#shipping-state").val();
        shipping_zip = $shippingAddress.find("#shipping-zip").val();
        shipping_country = $shippingAddress.find("#shipping-country").val();

        if (!shipping_first_name) {
          $shippingAddress.find('#divShippingFirstName .error-text').remove();
          $shippingAddress.find('#divShippingFirstName').addClass("error").addClass("transparent");
          $shippingAddress.find('#shipping-first-name').after("<ul class='error-text'><li>First Name is required</li></ul>");

          logger.info("no address first name");
          return false;
        }
        else {
          $shippingInfo.find('#divShippingFirstName').removeClass("error");
        }

        if (!shipping_last_name) {
          $shippingAddress.find('#divShippingLastName .error-text').remove();
          $shippingAddress.find('#divShippingLastName').addClass("error").addClass("transparent");
          $shippingAddress.find('#shipping-last-name').after("<ul class='error-text'><li>Last Name is required</li></ul>");

          logger.info("no last name");
          return false;
        }
        else {
          $shippingInfo.find('#divShippingLastName').removeClass("error");
        }

        if (!shipping_address1) {
          $shippingAddress.find('#divShippingAddress1 .error-text').remove();
          $shippingAddress.find('#divShippingAddress1').addClass("error").addClass("transparent");
          $shippingAddress.find('#shipping-address1').after("<ul class='error-text'><li>Address is required</li></ul>");

          logger.info("no shipping address 1");
          return false;
        }
        else {
          $shippingInfo.find('#divShippingAddress1').removeClass("error");
        }

        if (!shipping_zip) {
          $shippingAddress.find('#divShippingZip .error-text').remove();
          $shippingAddress.find('#divShippingZip').addClass("error").addClass("transparent");
          $shippingAddress.find('#shipping-zip').after("<ul class='error-text'><li>Zip code is required</li></ul>");

          logger.info("no shipping address 2");
          return false;
        }
        else {
          $shippingInfo.find('#divShippingZip').removeClass("error");
        }

        if (!shipping_state) {
          $shippingAddress.find('#divShippingState .error-text').remove();
          $shippingAddress.find('#divShippingState').addClass("error").addClass("transparent");
          $shippingAddress.find('#shipping-zip').after("<ul class='error-text'><li>State is required</li></ul>");

          logger.info("no shipping state");
          return false;
        }
        else {
          $shippingInfo.find('#divShippingState').removeClass("error");
        }

        if (!shipping_city) {
          $shippingAddress.find('#divShippingCity .error-text').remove();
          $shippingAddress.find('#divShippingCity').addClass("error").addClass("transparent");
          $shippingAddress.find('#shipping-city').after("<ul class='error-text'><li>City is required</li></ul>");

          logger.info("no shipping city");
          return false;
        }
        else {
          $shippingInfo.find('#divShippingCity').removeClass("error");
        }

        if (!shipping_country) {
          $shippingAddress.find('#divShippingCountry .error-text').remove();
          $shippingAddress.find('#divShippingCountry').addClass("error").addClass("transparent");
          $shippingAddress.find('#shipping-country').after("<ul class='error-text'><li>Country is required</li></ul>");

          logger.info("no shipping country");
          return false;
        }
        else {
          $shippingAddress.find('#divShippingCountry').removeClass("error");
        }
      }
       */

      var card_name = $paymentMethod.find("#card-name").val();
      var card_number = $paymentMethod.find("#card-number").val();
      var card_year = $paymentMethod.find("#card_expire-date_1i").val();
      var card_month = $paymentMethod.find("#card_expire-date_2i").val();
      var card_verify = $paymentMethod.find("#card-verify").val();

      /**
      if (!card_name) {
        $paymentMethod.find('#divCardName .error-text').remove();
        $paymentMethod.find('#divCardName').addClass("error").addClass("transparent");
        $paymentMethod.find('#card-name').after("<ul class='error-text'><li>Card Name is required</li></ul>");
        return false;
      } else {
        $paymentMethod.find('#divCardName').removeClass("error");
      }*/

      // don't valid card form fields when reuse card selected
      if(!reuse_card_this_time) {
        if (!card_number) {
          $paymentMethod.find('#divCardNumber .error-text').remove();
          $paymentMethod.find('#divCardNumber').addClass("error").addClass("transparent");
          $paymentMethod.find('#card-number').after("<ul class='error-text'><li>Card Number is required</li></ul>");
          logger.info("no card number");
          billingInfoValid = false;
        } else if (!$.payment.validateCardNumber(card_number)) {
          $paymentMethod.find('#divCardNumber .error-text').remove();
          $paymentMethod.find('#divCardNumber').addClass("error").addClass("transparent");
          $paymentMethod.find('#card-number').after("<ul class='error-text'><li>Card Number is not valid</li></ul>");
          logger.info("invalid card number");
          billingInfoValid = false;
        } else {
          $paymentMethod.find('#divCardNumber').removeClass("error");
        }

        if (!$.payment.validateCardExpiry(card_month, card_year)) {
          $paymentMethod.find('#divCardExpiry .error-text').remove();
          $paymentMethod.find('#divCardExpiry').addClass("error").addClass("transparent");
          $paymentMethod.find('#card-expiry').after("<ul class='error-text'><li>Card Number is not valid</li></ul>");
          logger.info("invalid card expiry");
          billingInfoValid = false;
        } else {
          $paymentMethod.find('#divCardExpiry').removeClass("error");
        }

        if (!card_verify) {
          $paymentMethod.find('#divCardVerify .error-text').remove();
          $paymentMethod.find('#divCardVerify').addClass("error").addClass("transparent");
          $paymentMethod.find('#card-verify').after("<ul class='error-text'><li>Card Verification Value is required</li></ul>");

          logger.info("no card verify");
          billingInfoValid = false;
        } else if (!$.payment.validateCardCVC(card_verify)) {
          $paymentMethod.find('#divCardVerify .error-text').remove();
          $paymentMethod.find('#divCardVerify').addClass("error").addClass("transparent");
          $paymentMethod.find('#card-verify').after("<ul class='error-text'><li>Card Verification Value is not valid.</li></ul>");

          logger.info("bad card CVC");
          billingInfoValid = false;
        } else {
          $paymentMethod.find('#divCardVerify').removeClass("error");
        }
      }

      if(!billingInfoValid) {
        logger.debug("billing info is invalid. returning");
        return false;
      }

      billing_info = {};
      shipping_info = {};
      billing_info.first_name = billing_first_name;
      billing_info.last_name = billing_last_name;
      billing_info.address1 = billing_address1;
      billing_info.address2 = billing_address2;
      billing_info.city = billing_city;
      billing_info.state = billing_state;
      billing_info.country = billing_country;
      billing_info.zip = billing_zip;
      billing_info.number = card_number;
      billing_info.month = card_month;
      billing_info.year = card_year;
      billing_info.verification_value = card_verify;

      /**
      if (shipping_as_billing) {
        shipping_info = $.extend({},billing_info);
        delete shipping_info.number;
        delete shipping_info.month;
        delete shipping_info.year;
        delete shipping_info.verification_value;
      } else {
        shipping_info.first_name = shipping_first_name;
        shipping_info.last_name = shipping_last_name;
        shipping_info.address1 = shipping_address1;
        shipping_info.address2 = shipping_address2;
        shipping_info.city = shipping_city;
        shipping_info.state = shipping_state;
        shipping_info.country = shipping_country;
        shipping_info.zip = shipping_zip;
      }*/

      var email = null;
      var password = null;
      var terms = false;
      var isLoggedIn = context.JK.currentUserId;
      if(!isLoggedIn) {
        email = $accountSignup.find('input[name="email"]').val()
        password = $accountSignup.find('input[name="password"]').val()
        terms = $accountSignup.find('input[name="terms-of-service"]').is(':checked');
      }

      $screen.find("#payment-info-next").addClass("disabled");
      $screen.find("#payment-info-next").off("click");
      rest.createRecurlyAccount({billing_info: billing_info, terms_of_service: terms, email: email, password: password, reuse_card_this_time: reuse_card_this_time, reuse_card_next_time: reuse_card_next_time})
        .done(function() {
          // so the user can hit back in checkoutOrder and not have to re-enter billing info right away
          checkoutUtils.setPreserveBillingInfo();
          $screen.find("#payment-info-next").on("click", next);

          if(isLoggedIn) {
            context.location = '/client#/checkoutOrder'
          }
          else {
            // this means the account was created; we need to reload the page for this to take effect
            context.JK.currentUserId = 'something'  // this is to trick layout.js from getting involved and redirecting to home screen
            context.location = '/client#/checkoutOrder'
            context.location.reload()
          }
        })
        .fail(errorHandling)
        .always(function(){
          $screen.find("#payment-info-next").removeClass("disabled");
        })
    }

    function errorHandling(xhr, ajaxOptions, thrownError) {
      logger.debug("error handling", xhr.responseJSON)
      if(xhr.responseJSON && xhr.responseJSON.errors) {
        $.each(xhr.responseJSON.errors, function(key, error) {
          if (key == 'number') {
            $paymentMethod.find('#divCardNumber .error-text').remove();
            $paymentMethod.find('#divCardNumber').addClass("error").addClass("transparent");
            $paymentMethod.find('#card-number').after("<ul class='error-text'><li>" + error + "</li></ul>");
          }
          else if (key == 'verification_value') {
            $paymentMethod.find('#divCardVerify .error-text').remove();
            $paymentMethod.find('#divCardVerify').addClass("error").addClass("transparent");
            $paymentMethod.find('#card-verify').after("<ul class='error-text'><li>" + error + "</li></ul>");
          }
          else if(key == 'email') {
            var $email = $accountSignup.find('input[name="email"]')
            var $field = $email.closest('.field')
            $field.find('.error-text').remove()
            $field.addClass("error").addClass("transparent");
            $email.after("<ul class='error-text'><li>" + error + "</li></ul>");
          }
          else if(key == 'password') {
            var $password = $accountSignup.find('input[name="password"]')
            var $field = $password.closest('.field')
            $field.find('.error-text').remove()
            $field.addClass("error").addClass("transparent");
            $password.after("<ul class='error-text'><li>" + error + "</li></ul>");
          }
          else if(key == 'terms_of_service') {
            var $terms = $accountSignup.find('input[name="terms-of-service"]')
            var $field = $terms.closest('.field')
            $field.find('.error-text').remove()
            $field.addClass("error").addClass("transparent");
            $accountSignup.find('.terms-of-service-label-holder').append("<ul class='error-text'><li>" + error + "</li></ul>");
          }
          else if(key == 'message') {
            $("#payment_error").text(error).removeClass('hidden')
          }
        });
      }
      else {
        $("#payment_error").text(xhr.responseText).removeClass('hidden')
      }


      $screen.find("#payment-info-next").on('click', next);
    }

    function toggleShippingAsBilling(e) {
      e.preventDefault();

      var shipping_as_billing = $(e.target).is(':checked');

      if (!shipping_as_billing) {
        $shippingAddress.removeClass("hidden");
      }
      else {
        $shippingAddress.addClass("hidden");
      }
    }

    function changeBillingInfo(e) {
      if(e) {
        e.preventDefault();
      }

      logger.debug("change billing info requested")

      // clear out the skip billing info behavior
      checkoutUtils.deletePreserveBillingInfo()

      renderAccountInfo();

      return false;
    }
    function toggleReuseExistingCard(e) {
      if(e) {
        e.preventDefault();
      }

      logger.debug("toggle reuse existing card")

      var reuse_existing = $(this).is(':checked');

      $('#billing-first-name').prop('disabled', reuse_existing);
      $('#billing-last-name').prop('disabled', reuse_existing);
      $('#billing-address1').prop('disabled', reuse_existing);
      $('#billing-address2').prop('disabled', reuse_existing);
      $('#billing-city').prop('disabled', reuse_existing);
      $('#billing-state').prop('disabled', reuse_existing);
      $('#billing-zip').prop('disabled', reuse_existing);
      $('#billing-country').prop('disabled', reuse_existing);

      $('#card-name').prop('disabled', reuse_existing);
      $('#card-number').prop('disabled', reuse_existing);
      $('#card_expire-date_1i').prop('disabled', reuse_existing);
      $('#card_expire-date_2i').prop('disabled', reuse_existing);
      $('#card-verify').prop('disabled', reuse_existing);

    }

    function events() {
      $screen.find("#payment-info-next").on('click', next);
      $shippingAsBilling.on('ifChanged', toggleShippingAsBilling);
      $reuseExistingCardChk.on('ifChanged', toggleReuseExistingCard);
      $alreadyEnteredJamTrackPrompt.find('.change-payment-info').on('click', changeBillingInfo)
    }

    function reset() {

    }

    function renderNavigation() {
      $navigation.html("");
      var navigationHtml = $(
        context._.template(
          $('#template-checkout-navigation').html(),
          {current: step, purchases_disable_class: gon.global.purchases_enabled ? 'hidden' : ''},
          {variable: 'data'}
        )
      );

      $navigation.append(navigationHtml);
    }

    function initializeControls() {
      $("form.payment-info").addClass(context.JK.currentUserId ? 'signed-in' : 'not-signed-in').iCheck({
        checkboxClass: 'icheckbox_minimal',
        radioClass: 'iradio_minimal',
        inheritClass: true
      });

      // Use jquery.payment to limit characters and length:
      $paymentMethod.find("#card-number").payment('formatCardNumber');
      $paymentMethod.find("#card-verify").payment('formatCardCVC');

      selectCountry = new context.JK.SelectLocation($('#billing-country'), null, null, app, false)
    }

    function initialize() {
      var screenBindings = {
        'beforeShow': beforeShow,
        'afterShow': afterShow,
        'beforeHide' : beforeHide
      };
      app.bindScreen('checkoutPayment', screenBindings);

      $screen             = $("#checkoutPaymentScreen");
      $paymentInfoPanel   = $screen.find("#checkout-payment-info");
      $navigation         = $screen.find(".checkout-navigation-bar");
      $billingInfo        = $paymentInfoPanel.find(".billing-address");
      $shippingInfo       = $paymentInfoPanel.find(".shipping-address");
      $paymentMethod      = $paymentInfoPanel.find(".payment-method");
      $accountSignup      = $paymentInfoPanel.find('.jamkazam-account-signup')
      $shippingAddress    = $paymentInfoPanel.find(".shipping-address-detail");
      $shippingAsBilling  = $paymentInfoPanel.find("#shipping-as-billing");
      $reuseExistingCard  = $paymentInfoPanel.find('.reuse-existing-card')
      $reuseExistingCardChk = $paymentInfoPanel.find('#reuse-existing-card')
      $existingCardEndsWith = $paymentInfoPanel.find('.existing-card-ends-with')
      $newCardInfo = $paymentInfoPanel.find('.new-card-info')
      $freeJamTrackPrompt = $screen.find('.payment-prompt.free-jamtrack')
      $noFreeJamTrackPrompt = $screen.find('.payment-prompt.no-free-jamtrack')
      $alreadyEnteredJamTrackPrompt = $screen.find('.payment-prompt.already-entered')


      if($screen.length == 0) throw "$screen must be specified";
      if($navigation.length == 0) throw "$navigation must be specified";

      initializeControls();

      events();
    }

    this.initialize = initialize;

    return this;
  }
})(window,jQuery);