var CartWidget = {
  _baseurl : '',
  _options : [],
  
  // set the base URL for adding/deleting/updating cart items
  setBaseURL : function (url) {
    CartWidget._baseurl = url;
  },
  
  // options for showing items
  setOptions : function (options) {
    CartWidget._options = options;
  },

  _formatPrice : function (price, currency) {
    price = price.toString();
    if(price.substring(price.length-3,price.length) == '.00') {
      price = price.substring(0,price.length-3);
    } else if(price.substring(price.length-2,price.length-1) == '.') {
      price += '0';
    }
    
    switch (currency.toUpperCase()) {
      case 'USD': price = '$'+price+' USD'; break;
      case 'SGD': price = '$'+price+' SGD'; break;
      case 'EUR': price = ' EUR '+price; break;
      case 'JPY': price = price+'円'; break;
    }

    return price;
  },
  
  _showLoading : function () { 
    $('.cart-empty').hide();
    $('.cart-details').hide();
    $('.cart-checkout').hide();
    $('.cart-loading').show();
    $('.cart-checkout').addClass ('disabled');
  },
   
  _hideLoading : function () {
    $('.cart-loading').hide(); 
    $('.cart-checkout').removeClass ('disabled');
  },

  _showEmptyMessage : function () {
    var len = $('.cart-item').length;
    if (len == 0) {
      $('.cart-empty').show();
      $('.cart-checkout input').addClass ('disabled');
      $('.cart-checkout input').attr ('disabled','disabled');
      $('.cart-details').hide();
      $('.cart-checkout').hide();
    }
    else {
      $('.cart-empty').hide();
      $('.cart-checkout input').removeClass ('disabled');
      $('.cart-checkout input').removeAttr ('disabled');
      $('.cart-details').show();
      $('.cart-checkout').show();
    }
  },
  
  // append a product to cart
  _appendProduct : function (product) {
    var clone = $('.cart-item-to-clone').clone(true);
    clone.removeClass ('cart-item-to-clone').addClass ('cart-item');

    var productUID = product.uid;
    clone.find ('input[name=quantity]').change (function () {
      CartWidget.updateProductQuantity (productUID, $(this).val());
    });
    clone.find ('.cart-item-delete').data ('uid', product.uid);
	
	clone.find ('.thumb').css ('background-image', 'url('+product.thumb_url+')');
    
    // User should not be able to edit number of preordered items
    if (product.preorder != null)
      clone.find ('input[name=quantity]').attr('disabled', 'disabled');
    	
    // update all attributes (uid, name, quantity, ...) 
    for (attribute in product) {
      var item  = clone.find ('.' + attribute);
      var value = product[attribute];
      
      // add currency type as well
      if (attribute == 'price') {
        if (typeof (product['currency']) != 'undefined') {
          value = CartWidget._formatPrice (value, product['currency']);
        }
      }

      // each item could appear more than once...
      item.each (function() {
        
        // depending on the type of the item we should update one thing or another
        if ($(this).is (':input')) {
          $(this).val (value);
        }
		else if ($(this).hasClass ('thumb')) {
	         // Do nothing, thumb is set above
			//$(this).css ('background-image', 'url('+value+')');
        }
        else if (typeof ($(this).attr('src')) != 'undefined') {
          $(this).attr ('src', value);
        }
        else { 
          $(this).html (value);
          // add ID to product link
          if (attribute == 'name') {
            $(this).attr ('href', $(this).attr ('href') + product.uid);
          }
        }
        $(this).show()
               .parents ('.container-' + attribute).show();
      });
    }

    clone.insertBefore ('.cart-loading');
    clone.show();
    return clone;
  },

  // finds given ProductUID in the list of items already loaded
  _existProductInList : function (productUID) {
    return ($('.cart-item input[name=uid][value=' + productUID + ']').length > 0);  
  },

  _getProductInList : function (productUID) {
    return $('.cart-item input[name=uid][value=' + productUID + ']').parents ('.cart-item');  
  },

  _refreshRows : function () {
    $('.cart-item')
      .removeClass ('odd')
      .filter (':odd')
      .addClass ('odd');
  },

  // refresh the TOTAL
  _refreshTotalPrice : function () {
    var total = 0;

    var response = CartWidget._queryServer (CartWidget._baseurl + "/total", null); 
    if (response != null && 'total' in response && 'currency' in response) {
      total = CartWidget._formatPrice (response['total'], response['currency']);
    }
    
    $('.cart-total').html (total)
      .stop(true, true)
      .effect ('highlight', {}, 1000);
  },
  
  // refresh the cart given the list of products
  _refresh : function (/*productsInCart = null*/) {
    var productsInCart = (arguments.length >= 1) ? arguments[0] : null;

    if (productsInCart != null) {
      for (var i = 0; i < productsInCart.length; i++) {
        CartWidget._appendProduct (productsInCart[i]);
      }
    }
    
    CartWidget._refreshTotalPrice();
    CartWidget._refreshRows();
    CartWidget._showEmptyMessage();
  },
  
  // add given product to the cart
  addToCart : function (productUID)
  {
    var response = CartWidget._queryServer (
      CartWidget._baseurl + "/add",
      { 'product' : productUID },
      !CartWidget._existProductInList (productUID) // show Loading if product does not exist
    );

    // once we have the response, we update quantity on existing products
    // or we append a new product
    if (response != null && 'product' in response)
    {
      if (CartWidget._existProductInList (productUID)) {
        CartWidget._getProductInList (response.product.uid)
          .find ('input[name="quantity"]')
          
          // following line solves a marginal case where the user clicks "add" superfast
          // NOTE: this line won't work: .val (response.product.quantity)
          .each (function () {
            if ($(this).val() < response.product.quantity) {
              $(this).val (response.product.quantity);
            }
          })
          .end()
          .stop(true, true)
          .effect ('highlight', {}, 1000);
      }
      else {
        CartWidget._appendProduct (response.product)
         .stop(true, true)
         .effect ('highlight', {}, 1000);
      }
    }
    // wrong response (highlight red if exists)
    else if (CartWidget._existProductInList (productUID)) {
      CartWidget._getProductInList (response.product.uid)
       .stop(true, true)
       .effect ('highlight', {'color' : 'red'}, 1000);
    }

    CartWidget._refresh();
  },

  deleteFromCart : function (productUID) {
    var response = CartWidget._queryServer (
      CartWidget._baseurl + "/delete",
      { 'product' : productUID },
      false
    );

    if (response != null && response.ok) {
      CartWidget._getProductInList (productUID)
       .stop(true, true)
       .fadeOut ('fast', function () {
         $(this).remove();
         CartWidget._refresh();
       });
    }
    else {
      CartWidget._getProductInList (productUID)
       .stop(true, true)
       .effect ('highlight', {color : 'red'}, 1500); 
    }
  },

  // add given product to the cart
  updateProductQuantity : function (productUID, quantity)
  {
    if (!CartWidget._existProductInList (productUID)) {
      return;
    }
      
    var response = CartWidget._queryServer (
      CartWidget._baseurl + "/update-quantity",
      { 'product' : productUID, 'quantity' : quantity},
      false
    );

    var deleteProduct = true;
    
    // once we have the response, we update quantity on existing products
    // or we append a new product
    if (response != null && 'product' in response)
    {
      if (response.product.quantity > 0) {
        deleteProduct = false;
        
        CartWidget._getProductInList (response.product.uid)
          .find ('input[name="quantity"]')
          .val (response.product.quantity)
          .end()
          .stop(true, true)
          .effect ('highlight', {}, 1000);
      }
    }

    // if product quantity = 0, or error returned, the product is no longer valid
    if (deleteProduct) {
      CartWidget._getProductInList (productUID)
      .stop(true, true)
      .fadeOut ('fast', function () {
        $(this).remove();
        CartWidget._refresh();    
      });
    }
    else {    
      CartWidget._refresh();
    }
  },
  
  // reload/refresh cart
  reloadCart : function ()
  {
    $('.table-display').find ('.cart-item').remove();    
    var response = CartWidget._queryServer (
      CartWidget._baseurl + "/list",
      null
    );

    if ((response != null) && ('products' in response)) {
      CartWidget._refresh (response.products);
    }
    else {
      CartWidget._refresh();
    }
  },

  // return null on failure and the response object when succeds
  _queryServer : function (queryURL, information /* show loading */) {
    var loading = (arguments.length >= 3 ? arguments[2] : true);
    var answer = null;

    // merge information and options
    if (information == null) { information = {'options' : CartWidget._options.join(',')}; }
    else                     { information['options'] = CartWidget._options.join(','); }
    
    if (loading) CartWidget._showLoading();
    $.ajax ({
      url      : queryURL,
      type     : 'POST',
      cache    : false,
      async    : false,
      data     : information,
      dataType : 'json',
      success : function (response) {
        if (response.ok)
          answer = response;
      },
      error   : function () {
        // alert ("An error occurred :(");
        //TODO: show a refresh button in the cart when an error occurrs
      }
    });
    if(loading) CartWidget._hideLoading();
    return answer;
  }
};

