var gg;
if (!gg) {
  gg = {};
}
(function() { // So we can have private functions
  if (!gg.Cart) {
    gg.Cart = {
      current: null,
      ejs: null,
      guid: null,
      subsite_id: 0
    };
  }
  (function() {
    gg.Cart.addCartQuantityUI = function(el) {
      el.data("oldvalue", parseInt(el.val()))
        .data("sku", parseInt(el.id().replace("cart_quantity_", "")))
        .keydown(onKeypress);
      addObserver(el);
    };

    // PRIVATE FUNCTIONS:

    var addObserver = function(el) {
      var interval = null;
      el.focus(function() {
        interval = setInterval(Observer(el), 500);
      }).blur(function() {
        clearInterval(interval);
      });
    };

    var blockSubmit = function(ev) {
      ev.preventDefault();
    };

    var closeMessage = function(ev) {
      if (ev) {
        ev.preventDefault();
        ev.stopPropagation(); // needs cross browser testing
      }
      $(document).unbind("click", closeMessage);
      var tip = $(".cart_delete_prompt");
      tip
        .trigger("closemessage")
        .fadeOut("normal", function() {
          tip.remove();
        });
    };

    var Observer = function(el) {
      return function() {
        var v = parseInt(el.val());
        if (el.val() != el.data("oldvalue")) {
          if (!el.val().length || 0 == v) {
            if (!el.data("deleteInProgress")) {
              el.data("deleteInProgress", true);
              showDeleteMessage(el, 0 === v ? 500 : 5000);
              //updateValue(el, 0);
            }
          } else if (0 > v || !(0 >= v || 0 <= v)) { // negative & NaN
            el.val(el.data("oldvalue"));
          } else if (v > gg.Cart.MAX_SIZE - gg.Cart.current.reservations.length + gg.Cart.current.skus[el.data("sku")].quantity) {
            closeMessage();
            el.removeData("deleteInProgress");
            showErrorMessage(el, Locale.max_cart_size(gg.Cart.MAX_SIZE));
            updateValue(el, el.data("oldvalue"));
          } else {
            closeMessage();
            el.removeData("deleteInProgress");
            el.data("oldvalue", v);
            updateAJAX(el, v);
            updateValue(el, v);
          }
        }
      };
    };

    var onKeypress = function(event) {
      var el = $(this);
      var key = event.keyCode;
      switch(key) {
        case 38:  // up
        case 39:  // right
        //case 102: // numpad 6 (right)
        //case 104: // numpad 8 (up)
          var v = Math.min(el.data("oldvalue") + 1, gg.Cart.MAX_SIZE - gg.Cart.current.reservations.length + gg.Cart.current.skus[el.data("sku")].quantity);
          if (el.data("deleteInProgress")) {
            v--;
          }
          closeMessage();
          el.data("oldvalue", v);
          updateAJAX(el, v);
          updateValue(el, v);
          return false;
        case 37:  // left
        case 40:  // down
        //case 98:  // numpad 2 (down)
        //case 100: // numpad 4 (left)
          if (!el.data("deleteInProgress")) {
            closeMessage();
          }
          v = Math.max(el.data("oldvalue") - 1, 0);
          if (v) {
            el.data("oldvalue", v);
            updateAJAX(el, v);
          } else {
            if (!el.data("deleteInProgress")) {
              el.data("deleteInProgress", true);
              showDeleteMessage(el);
            }
          }
          updateValue(el, v);
          return false;
      }
    };

    var showDeleteMessage = function(el, interval) {
      clearTimeout(el.data("updateInterval")||-1);
      var show = function() {
        showMessage(el, "<p>" + (interval ? "Do" : "Are you sure") + " you want to remove this item?</p><a href='#'>Yes</a><a href='#'>No</a>")
          .bind("closemessage", function() {
            updateValue(el, el.data("oldvalue"));
            el.removeData("deleteInProgress");
          }).find("a:first").click(function() {
            gg.Cart.removeSku(el.data("sku"), gg.Cart.showCartDialog);
          });
      };
      if (interval) {
        el.data("updateInterval", setTimeout(show, interval));
      } else {
        show();
      }
    };

    var showErrorMessage = function(el, msg) {
      showMessage(el, "<p>" + msg + "</p><a href='#'>OK</a>");
    };

    var showMessage = function(el, html) {
      var tip = $("<div>");
      tip
        .addClass("cart_delete_prompt")
        .html("<div class='top'></div><div>" + html + "</div><div class='bottom'></div>");
      var d = $("#dialog_cart").parent();
      d.append(tip);
      tip
        .css({top: (el.offset().top - d.offset().top) + (el.height() - tip.height()) / 2,
               left: (el.offset().left - d.offset().left) - tip.width() })
        .find("a")
        .click(closeMessage);
      $(document).one("click", closeMessage);
      tip.fadeIn();
      return tip;
    };

    var updateValue = function(el, value) {
      el.val(value);
      el.closest("table").find(".checkout_button").click(blockSubmit);
      if (el.data("unitprice")) {
        var unitprice = el.data("unitprice");
      } else {
        unitprice = parseFloat(el.parent().prev().text().replace("$", "").replace(",", ""));
        el.data("unitprice", unitprice);
      }
      el.parent().next().find("span")
        .stop(true, true)
        .css({ backgroundColor: $("#dialog_cart").css("backgroundColor") })
        .text(fl.Formatter.currency(unitprice * 1000 * value / 1000))
        .animate({ backgroundColor: el.closest("tr").css("backgroundColor") });
      var total = 0;
      $("#dialog_cart td.total span").each(function() {
        total += parseFloat($(this).text().replace("$","").replace(",",""));
      });
      $("#cart_subtotal").text(fl.Formatter.currency(total));
    };

    var updateAJAX = function(el, value) {
      clearTimeout(el.data("updateInterval")||-1);
      el.data("updateInterval", setTimeout(function() {
        gg.Cart.updateSkuQuantity(el.data("sku"), value, function(cart, msg) {
          gg.Cart.reservationsBySku(); // to update quantity
          if (msg || cart.user_message) {
            showErrorMessage(el, msg || cart.user_message);
            el.data("oldvalue", gg.Cart.current.skus[el.data("sku")].quantity);
            updateValue(el, gg.Cart.current.skus[el.data("sku")].quantity);
          }
          el.closest("table").find(".checkout_button").unbind("click", blockSubmit);
        });
      }, 1000));
    };
  })();

  gg.Cart.countdown = function(selector, duration, expiredMessage) { // TODO: batch
    var countdown = null;
    var endTime = (new Date()).getTime() + 1000 * duration;
    var updateCountdown = function() {
      if (!countdown) {
        countdown = $(selector);
      }
      if (countdown.filter(":visible").length) {
        var timeRemaining = endTime - (new Date()).getTime();
        if (120000 > timeRemaining) {
          countdown.parent().addClass("expiring");
        }
        if (0 < timeRemaining) {
          //if (120000 < timeRemaining) {
          //  countdown.text(fl.Util.secondsToMinutes(Math.round(timeRemaining/1000)));
          //} else {
            countdown.text(fl.Util.secondsToMinutesSeconds(Math.round(timeRemaining/1000)));
          //}
          setTimeout(updateCountdown, 1000 - (new Date()).getTime() % 1000); // recalc each time, due to possible latency
        } else {
          countdown.parent().replaceWith(expiredMessage);
        }
      }
    };
    setTimeout(updateCountdown, 1000);
};

  /** @deprecated */
  gg.Cart.display = function() {
    gg.Cart.showCartDialog();
  };

  gg.Cart.itemExpirationMessage = function(skus) {
    var selector = "#cart_container .reservation_time span";
    var single = false;

    if ("string" == typeof skus.expiration) {
      selector = "#cart_sku_" + skus.sku_data.sku_id + " ~ td span.countdown";
      skus = { 0: skus };
      single = true;
      //return; // comment this, and the return in gg.Cart.countdown, to enable new countdown feature for individual skus
    } else if(!skus){
      skus = gg.Cart.reservationsBySku();
    }

    if (1 < gg.Cart.current.quantity && !single) {
      var minExpiration = gg.Cart.minExpiration();
      if ((new Date()).getTime() >= minExpiration) {
        return Locale.others_may_purchase_these_items;
      }
      minExpiration = gg.Cart.secondsUntilCartExpires();
      gg.Cart.countdown(selector, minExpiration, Locale.others_may_purchase_these_items);
      return Locale.these_items_reserved(minExpiration);
    } else if (gg.Cart.current.quantity) {
      for (var sku in skus) {
        if ((new Date()).getTime() > skus[sku].expiration_ms) {
          return Locale.others_may_purchase_this_item;
        }
      }
      var expiration = Math.floor((skus[sku].expiration_ms - (new Date()).getTime() - gg.Cart.current.serverClockDelta) / 1000);
      gg.Cart.countdown(selector, expiration, Locale.others_may_purchase_this_item);
      return Locale.this_item_reserved(expiration);
    }

    return null;
  };

  gg.Cart.numberSkus = function(callback) {
    if (gg.Cart.current) {
      callback(gg.Cart.current.quantity);
    }
    var ssni = fl.Util.readCookie("ssni");
      if (!ssni) {
      fl.Util.expireCookie("ssni");
      callback(0);
    } else {
      callback(ssni.split(":")[0]);
    }
  };
  gg.Cart.numberUnits = function(callback) {
    if (gg.Cart.current && gg.Cart.current.reservations) {
      callback(gg.Cart.current.reservations.length);
    }
    var ssni = fl.Util.readCookie("ssni");
      if (!ssni) {
      fl.Util.expireCookie("ssni");
      callback(0);
    } else {
      callback(ssni.split(":")[1]);
    }
  };

  /** @deprecated */
  gg.Cart.refresh = function() {
    gg.Cart.showCartDialog();
  };

  gg.Cart.getCartDialog = function() {
    return fl.Util.getDialog("dialog_cart", {
      title: Locale.your_cart,
      width: 710,
      dialogClass: "cart-dialog"
    });
  };

  gg.Cart.showCartDialog = function() {
    var d = gg.Cart.getCartDialog();
    gg.Cart.numberSkus(function(count) {
      d.dialog("option", { height: 221 + 111 * count }); // Guesstimate height of modal
    });
    if (!d.filter(":visible").length) {
      d.html(Locale.please_wait_loading_spin).dialog("open");
    }
    //return;
    gg.Cart.retrieve(function(cart) {
      if (!gg.Cart.ejs) {
        gg.Cart.ejs = new EJS({ text: escapeEJSTemplate($('#cart_layout').html()) });
      }
      var content = gg.Cart.ejs.render({ cart: cart });
      d.html(content);
      if (!d.html().replace(/\s/g, '').length) { // total hackfest.  IE sometimes fails to append html
        try {
          d[0].innerHTML = content;
        } catch(_) {}
      }
      if ($.browser && parseInt($.browser.version) < 7) {
        d.find("a.sprite").each(function() {
          $(this).css({ width: $(this).width() });
        });
      }
      d.dialog("option", { height: "auto" })
        .css({ height: "auto" }); // un-guesstimate
      $(".cart_quantity").each(function(_, el) {
        gg.Cart.addCartQuantityUI($(el));
      });
    });

    // Track show-cart action when user clicks on Cart link, as we do actual cart logic
    // in various places (client-side, server-side, cart-service) depending on the context.
    Gilt.Atlas.requestResource('http://view.atdmt.com/action/' + Gilt.Atlas.tagNameForSubsite(gg.Site.currentSubsite.key) + '_cart_index');
  };

  gg.Cart.updatePageCartCount = function(newSkuCount, newUnitCount) {
    var f = function(count) {
      var d = new Date();
      if (0 == count) {
        fl.Util.expireCookie("ssni");
      } else if (newUnitCount) {
        fl.Util.setPersistentCookie("ssni", newSkuCount + ":" + newUnitCount);
      }
      $("#carousel-nav-cart span").text("(" + count + ")");
    };
    if (newUnitCount) {
      f(newUnitCount);
    } else {
      gg.Cart.numberUnits(f);
    }
    startCookieWatchIfNotStarted();
  };

  // Private

  var cookieWatchStarted = false;
  var startCookieWatchIfNotStarted = function() {
    if (!cookieWatchStarted) {
      fl.Util.watchCookie("ssni", function(newCount) {
        if (!newCount) {
          newCount = "0:0";
        }
        $("#carousel-nav-cart span").text("(" + newCount.split(":")[1] + ")");
      });
      cookieWatchStarted = true;
    }
  };

  var escapeEJSTemplate = function(template) {
    return template.replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/<\/JS>/g, '').replace(/JS/g, '%');
  };
})();

