// shorthand for passing an instance method as an event handler
Function.prototype.as_event_handler = function(tgt) {
  var me = this;
  return(function(evt) {
    me.apply(tgt);
    
    if(evt && evt.stopPropagation) evt.stopPropagation();
    return false;
  }); 
};

Function.prototype.as_handler = function(tgt) {
  var me = this;
  return(function() {
    return me.apply(tgt, arguments);
  }); 
};

var ProductChooser = function(which, submit_callback, before_submit_callback) {
  // set things up
  this._chooser = $(which);
  if (!this._chooser) return false;
  this._chooser.data("chooser_obj", this);
  this._quantity_field = this._chooser.find('.quantity');
  this._base_price_display = this._chooser.find('.price');
  this._submit_button = this._chooser.find('.addToCart');
  this._options_url = this._chooser.find('a.optionsLink').attr('href');
  this._variation_details = {};
  this._variation_details.product_variation_id = this._chooser.find('[name*=product_variation_id]');
  this._variation_details.product_variation_price = this._chooser.find('[name*=product_variation_price]');
  this._chooser.find('SELECT').change( this.update_details.as_event_handler(this) );
  this.update_details();
  if (submit_callback)
    this.ajax_with_callback(submit_callback, before_submit_callback);
}

ProductChooser.prototype.ajax_with_callback = function(after_submit_callback, before_submit_callback) {
  var me = this;
  var submitForm = me._chooser.find('FORM');
  var ajax_submit = function(e) {
    $.ajax({
      type: "POST",
      url: submitForm.attr('action') + ".json",
      data: submitForm.serialize(),
      success: after_submit_callback,
      dataType: "json"
    });
    if (e && e.stopPropagation) e.stopPropagation();
    return false;
  };
  if (before_submit_callback) {
    submitForm.submit(function() {
      before_submit_callback(ajax_submit);  
      return false; 
    }); 
  } else {
    submitForm.submit(ajax_submit);
  }
};

ProductChooser.prototype.update_details = function () {
  var me = this;

  if (this._chooser.hasClass('doesRemote')) {
    $.getJSON(this._options_url, 
              this.current_variation_options(),
              this.update_variation_options.as_handler(this));
  } else {
    this.real_update_details();
  }
};

ProductChooser.prototype.current_variation_options = function () {
  var options = {}
  this._chooser.find('SELECT,INPUT[name*=part_]:not(:disabled)').each(function () {
      options[$(this).attr('name')] = $(this).val();
      });
  return options;
};

ProductChooser.prototype.update_variation_options = function(data) {
  this._variation_details.product_variation_id.val(''); 
  this._variation_details.product_variation_price.val('');
  var me = this;
  $.each(data, function(key, value) {
    var control = null;
    if(me._variation_details[key]) { 
      control = me._variation_details[key];
    } else {
      control = me._chooser.find("select[name=" + key + "],input[name=" + key + "]");
    }
    if (control.is("SELECT")) {
      var select = control.html(me.make_options(key, value)).get()[0];
      select.selectedIndex = 0;
    } else if (control.is("INPUT")) {
      if (!key.match(/^part_/)) {  // Don't change values of part_n elements
        control.val(value);
        control.change();
      }
    } else {
      if (value) {
        control.show();
      } else {
        control.hide();
      }
    }
  });
  this.real_update_details();
};

ProductChooser.prototype.make_options = function(key, options) {
  return("<option value=\"\">-- select --</option>" +
      $.map(options, function(item) {
        // part_X should be ["label", "quantity"], instead of just "label" 
        if (key.match(/^part_/)) {
          var lab = item[0];
          var out_of_stock = (item[1] == "0");
          if(out_of_stock) lab = lab + " [out of stock]";
          return('<option value="' + encodeURI(lab).replace('+', ' ') + '"' + (out_of_stock ? ' disabled="disabled"' : '') + '>' + lab + '</option>');
        } else {
          return('<option value="' + encodeURI(item).replace('+', ' ') + '">' + item + '</option>');
        }
      }));
};

ProductChooser.prototype.atc_no_product = function() {
  var vari_id = this._variation_details.product_variation_id.val();
  if (vari_id == null || $.trim(vari_id) == '')
    this._chooser.find('.must-select').fadeIn('fast');
};

ProductChooser.prototype.real_update_details = function() {
  var vari_id = this._variation_details.product_variation_id.val();
  var vari_price = this._variation_details.product_variation_price.val();
  var vari_quantity = Number(this._quantity_field.val());
  $('.product_info form .productNotice').slideUp(0);
  if(vari_id != null && $.trim(vari_id) != '' && vari_quantity > 0) {
    this._submit_button.show();
    this._submit_button.unbind("click", this.atc_no_product.as_event_handler(this));
    this._chooser.find('.must-select').fadeOut('fast');
  } else {
    this._submit_button.show().
      unbind("click", this.atc_no_product.as_event_handler(this)).
      bind("click", this.atc_no_product.as_event_handler(this));
  }
};

$(function() {
  var product_notify_callback = function(data) {
    if ($('.product_info form').find('.productNotice').length == 0) {
      $('.product_info form').append('<div class="productNotice"></div>');
      $('.product_info form .productNotice').slideUp(0);
	  $('.product_info form .productNotice').html('<p> The product was added to your cart. </p><a href="/cart">View cart</a> ');
	  $('.product_info form .productNotice').slideDown(150);
    }
    else if (jQuery('.product_info form select').val() != '')  {
     	$('.product_info form .productNotice').fadeOut(0, function() {
    		$('.product_info form .productNotice').fadeIn(150);
    	});
   	}
  }
  var age_verify_callback = null;
  var chooser_base = $('.product_info');

  if (chooser_base.is(':has(form.verifyAge)')) {
    age_verify_callback = function(submit_callback) {
      var submitForm = $(this); 
      if(submitForm.is(".verifiedAge")) { 
        return true;
      } else {
        $(document.body).append('<div id="verify_form"></div>');
        var d = $('#verify_form');
        d.load('/cart/verify_age', null,
          function() {
            d.find('form').submit(function() { return false; });
            d.dialog( {
                modal: true,
                height: 320,
                width: 520,
                buttons: {
                "Add To Cart": function() {
                  var form = d.find('form')[0];
                  $.post(form.action, $(form).serialize(), function(data, status) {
                    if(data.length == 1) { // empty result set
                      submitForm.addClass('verifiedAge');
                      submit_callback();
                      d.dialog('destroy');
                    } else {
                      d.html(data);
                      var h = $('#verify_form').css('height', 'auto').innerHeight(); 
                      $('#verify_form').parent().parent().height(h + 50);
                    }
                  });
                },
                "Cancel": function() {
                  d.dialog('destroy');
                }
              }
            });
          });
        return false;
      };
    }
  } 

  var chooser = new ProductChooser(".product_info", product_notify_callback, age_verify_callback);
});
