var safVer = navigator.userAgent.match(/Safari\/(\d)\d\d\.\d/)
if (!safVer || parseInt(safVer[1]) > 3) {

/*=============================================================
  THE BASKET
-------------------------------------------------------------*/
Basket = function (element, cookieScope, options) {
  var me = this;

  this.options = options || {};
  this.options.basketName = this.options.basketName || "basket";

  element = $(element);
  if (!element) { return; }
  element.basket = this;
  this.container = element;
  this.detailsBox = element.down('.basket_details');
  this.noticeBox = element.down('.basket_notice');
  this.summaryBox = element.down('.basket_summary');

  this.pullDownURL = element.getAttribute('pull_down_url');
  this.summaryBox.onclick = function () {me.toggle(); return false; }

  this.noticeTimeout = null;

  // Load state from cookie.
  var pfx = cookieScope + "_basket_";
  this.persistentContents = new Cookie(pfx + 'contents', Cookie.days(3));
  this.persistentQuantity = new Cookie(pfx + 'quantity', Cookie.days(3));
  this.updateQuantity(null, this.persistentQuantity.get() || 0);
}

// Create a temporary filler for each productId in the cookie.
Basket.prototype.initFillers = function () {
  var pContents = this.persistentContents.get();
  if (!pContents) { return; }
  unescape(pContents).split(',').each(function(productId) {
    var filler = new BasketFiller(productId);
    filler.state('checkout');
  });
}

// show/hide the basket
Basket.prototype.pullDown = function () {
  var me = this;

  var emt = this.detailsBox.down('.basket_empty');
  emt.update("You have nothing in your " + this.options.basketName);

  new Effect.SlideDown(
    this.detailsBox,
    {
      duration: 0.25,
      afterFinish: function () {me.hideNotification();}
    }
  );
  this.summaryBox.addClassName('basket_active');
  this.summaryBox.blur();
}

Basket.prototype.pullUp = function () {
  new Effect.SlideUp(this.detailsBox, {duration: 0.1});
  this.summaryBox.addClassName('basket_active');
  this.summaryBox.blur();
}

Basket.prototype.toggle = function () {
  // if the basket is showing, just hide it
  if (this.detailsBox.visible()) {
    this.pullUp();
    return false;
  }

  // if the basket has valid contents, just show it
  if (!this.detailsBox.empty()) {
    this.pullDown();
    return false;
  }

  // otherwise, retrieve the basket via Ajax
  var me = this;
  this.showSpinner('Fetching...');
  new Ajax.Updater(
    this.detailsBox,
    this.pullDownURL,
    { onSuccess: function () { setTimeout(function () { me.pullDown() }, 0) } }
  );

  return true;
}

// notifications
Basket.prototype.showSpinner = function (msg) {
  if (!msg) {msg = '';}
  this.showNotification(
    '<div><img src="/static/images/spinner.gif" />' + msg + '</div>',
    true
  );
}

Basket.prototype.showError = function (msg, duration) {
  this.showNotification(
    '<div><span class="basket_errorMessage">' + msg + '</span></div>',
    duration
  );
}

Basket.prototype.showNotification = function (notice, duration) {
  this.noticeBox.update(notice);

  if (!this.noticeBox.visible()) {
    if (this.detailsBox.visible()) {
      this.noticeBox.show();
    } else {
      new Effect.SlideDown(this.noticeBox, {duration: 0.4});
    }
  }

  if (this.noticeTimeout) { clearTimeout(this.noticeTimeout); }

  if (!duration) { duration = 3000; }

  var me = this;
  if (duration != true) {
    var fn = this.detailsBox.visible() ?
      function(){me.noticeBox.hide();} :
      function(){new Effect.SlideUp(me.noticeBox, {duration:0.2});}

    this.noticeTimeout = setTimeout(fn, duration);
  }

  return notice;
}

Basket.prototype.hideNotification = function () {
  if (this.noticeTimeout) { clearTimeout(this.noticeTimeout); }
  if (this.noticeBox.visible()) {
    new Effect.SlideUp(this.noticeBox, {duration:0.2});
  }
}

// get/set subtotal
Basket.prototype.getSubtotal = function () {
  if (!this.subtotal) {this.subtotal = this.detailsBox.down('.basket_price');}
  return parseFloat(this.subtotal.innerHTML.gsub(/[\$,]/,''));
}

Basket.prototype.updateSubtotal = function (inc, exact) {
  if (!this.subtotal) {this.subtotal = this.detailsBox.down('.basket_price');}
  if (inc != null) { exact = this.getSubtotal() + inc; }
  this.subtotal.update('$' + exact.toFixed(2));
  return exact;
}

// get/set quantity
Basket.prototype.getQuantity = function () {
  var quantity = 0;
  var qSpan = this.summaryBox.down('b');
  if (qSpan) {
    quantity = qSpan.innerHTML;
  } else {
    quantity = this.persistentQuantity.get();
  }
  return parseInt(quantity);
}

Basket.prototype.updateQuantity = function (inc, exact) {
  if (inc != null) { exact = this.getQuantity() + inc; }
  exact = Math.max(0, exact);
  var plural = exact == 1 ? 'item' : 'items';
  var msg = "<b>"+exact+"</b> "+plural+" in " + this.options.basketName;
  this.summaryBox.update(msg);

  if (exact == 0) {
    var tbl = this.detailsBox.down('.basket_table');
    if (tbl) {tbl.hide();}
    var emt = this.detailsBox.down('.basket_empty');
    if (emt) {
      emt.show();
    }
  }

  return exact;
}

/*=============================================================
  BASKET ITEMS
-------------------------------------------------------------*/
BasketItem = function (productId) {
  this.basket = Basket.instance;
  this.productId = productId;
  this.row = this.basket.container.down('tr[product_id="'+productId+'"]');
  this.filler = new BasketFiller(this.productId);
}

BasketItem.updateQuantity = function (productId, inc, exact) {
  var item = new BasketItem(productId);

  var currentQuantity = item.getQuantity();
  if (inc == null) { inc = parseInt(exact) - currentQuantity;}
  if (currentQuantity + inc < 1) { return false; }
  item.setQuantity(inc);
  item.basket.updateQuantity(inc);
  item.basket.updateSubtotal(inc * item.getPrice());

  return false;
}

// adding items to basket
BasketItem.add = function (productId) {
  var item = new BasketItem(productId);
  item.added();
  return false;
}

// removing items from basket
BasketItem.remove = function (productId) {
  var item = new BasketItem(productId);
  item.removed();
  return false;
}

// get/set quantity
BasketItem.prototype.getQuantity = function () {
  if (!this.qField) {this.qField = this.row.down('.basket_quantifier input');}
  return parseInt(this.qField.value);
}

BasketItem.prototype.setQuantity = function (inc, exact) {
  if (!this.qField) { this.qField = this.row.down('.basket_quantifier input'); }
  if (!this.qDisplay) { this.qDisplay = this.row.down('.basket_quantity'); }
  if (inc != null) { exact = this.getQuantity() + inc; }
  this.qField.value = exact;
  this.qDisplay.update(exact);

  var control = this.row.down('.basket_quantifier');
  new Ajax.Request(
    control.getAttribute('update_url'),
    { parameters: Form.serialize(control) }
  );

  return exact;
}

// get price (no need to set it -- YAGNI)
BasketItem.prototype.getPrice = function (productId) {
  if (!this.pDisplay) { this.pDisplay = this.row.down('.basket_itemPrice'); }
  return parseFloat(this.pDisplay.innerHTML.gsub(/[\$,]/,''));
}

BasketItem.prototype.added = function () {
  this.basket.showSpinner('Adding...');
  this.filler.state('adding');
  this.basket.detailsBox.update('').hide();

  var me = this;
  new Ajax.Request(
    this.filler.add_url,
    {
      onFailure: function (transport) {
        me.basket.showErrorMessage(transport.responseText);
        me.filler.state('add');
      },
      onSuccess: function (transport) {
        me.basket.showNotification(transport.responseText);
        me.basket.updateQuantity(null, me.basket.persistentQuantity.get() || 1),
        me.filler.state('checkout');
      }
    }
  );
}

BasketItem.prototype.removed = function () {
  var me = this;
  this.filler.state('removing');
  this.removeLink = this.row.down('.basket_itemRemoveLink');
  new Ajax.Request(
    this.removeLink.getAttribute('remove_url'),
    { onSuccess: function () { me.filler.state('add'); } }
  );
  this.removeLink.hide();
  new Effect.Fade(this.row, {duration: 0.5});
  var q = this.getQuantity();
  var p = this.getPrice();
  this.basket.updateSubtotal(0 - (q * p));
  this.basket.updateQuantity(0 - q);
}

/*=============================================================
  BASKET FILLERS
-------------------------------------------------------------*/
BasketFiller = function (productId) {
  this.productId = productId;
  this.elements = $$('.basket_filler[product_id="'+productId+'"]');
  if (!this.elements || this.elements.length < 1) { this.elements = false; }
  if (this.elements) {
    this.add_url = this.elements.first().getAttribute('add_href');
  }
}

BasketFiller.prototype.state = function (prefix) {
  if (!this.elements) { return false; }
  this.elements.each(function(link) {
    link.update(link.getAttribute(prefix+'_text'));
    link.href = link.getAttribute(prefix+'_href');
    var js = link.getAttribute(prefix+'_function');
    if (js) {
      link.onclick = function () { return eval(js); }
    } else {
      link.onclick = null;
    }
    link.className = 'basket_filler ' + link.getAttribute(prefix+'_class');
  });
}


/*=============================================================
  FIRE IT UP
-------------------------------------------------------------*/
  Basket.initialise = function (scopeString, options) {
    var bsktElement = $('basket_');
    if (bsktElement) {
      Basket.instance = new Basket(bsktElement, scopeString, options);
    }
  }

  Basket.initFillers = function () {
    if (Basket.instance) { Basket.instance.initFillers(); }
  }

  Event.observe(window, 'load', function () {Basket.initFillers()});
}
