
generic.checkout = {};

/**
 * generic.checkout.cart 
 * - depends on: generic.cookie, generic.jsonrpc
 */ 
generic.checkout.cart = ( function() {
    var CartResult = function(responseData) {
        var data = responseData;
        var cartItem = {
            product: { 
                sku: {}
            }
        };
        var cartMethod;
        var totalCartItems;
        var cartSubtotal;
        var transData = {};

        if (data.ac_results &&
                Object.isArray(data.ac_results) && 
                data.ac_results[0]) {
            if (data.ac_results[0].result &&
                    data.ac_results[0].result.CARTITEM) {
                var item = data.ac_results[0].result.CARTITEM;
                var prodRegEx = /^prod\.(.+)$/;
                var skuRegEx = /sku\.(.+)$/;
                var prodObj = { sku: {} };
                for (var prop in item) {
                    var newPropName = null;
                    var prodResult = prop.match(prodRegEx);
                    if (prodResult && prodResult[1]) {
                        newPropName = prodResult[1];
                        cartItem.product[newPropName] = item[prop];
                    }
                    if (!newPropName) {
                        var skuResult = prop.match(skuRegEx);
                        if (skuResult && skuResult[1]) {
                            newPropName = skuResult[1];
                            cartItem.product.sku[newPropName] = item[prop];
                        }
                    }
                    if (!newPropName) {
                        cartItem[prop] = item[prop];
                    }
                }
            }
            if (data.ac_results[0].action) {
                cartMethod = data.ac_results[0].action;    
            }
            if (data.trans_data.items_count) {
                totalCartItems = data.trans_data.items_count;
            }
            if (data.trans_data.subtotal) {
                cartSubtotal = data.trans_data.subtotal;
            }
        }
        this.getItem = function() {
            return cartItem;
        };
        this.getMethod = function() {
            return cartMethod;
        };
        this.getCartItemsCount = function() {
            return totalCartItems;
        };
        this.getCartSubtotal = function() {
            return cartSubtotal;
        }     
    };
    return {
        setCookie: false, 
    
        order: new Hash(),
        payments: new Array(),
        carts: new Hash(), 
        items: new Array(),
        samples: new Array(),
     
        totalShoppedItems: 0, 
        totalItems: 0,
     
        transactionParams: {
    	transactionFields: {
        			"trans_fields" : ["TRANS_ID", "payments"]
    		},
    	paymentFields: {
        			"payment_fields" : ["address", "PAYMENT_TYPE", "PAYMENT_AMOUNT", "TRANS_PAYMENT_ID"]
    		},
    	orderFields: {
        			"order_fields" : ["items", "samples", "address", "TRANS_ORDER_ID"]
    		}
        },

        itemTypes: { 
        	"product" : {
        		"id": "SKU_BASE_ID",
        		"_SUBMIT" : "cart"
        	},
        	"giftcard" : {
        		"id": "CART_GIFTCARD_ID",
        		"_SUBMIT" : "giftcard"
        	},
        	"collection" : {
        		"id": "SKU_BASE_ID",
        		"_SUBMIT" : "collection.items"
        	},
        	"favorites" : {  
        		"id": "SKU_BASE_ID",
        		"_SUBMIT" : "alter_collection"
        	}
        },

        initialize: function(args) { 
        	Object.extend(this, args); // copy args to obj
        },
    
        getCartTotals: function() {
    	    var cookie = generic.cookie("cart");
    	    if (cookie && cookie!==null) {
    	        // console.log("generic.cart.getCartTotals cookie: "+Object.toJSON(cookie));
    	        Object.extend(this, cookie);
    	        generic.events.fire({event:'cart:countsUpdated'});
    	    } else {
    	        // console.log("generic.cart.getCartTotals !cookie");
    	        this.getCart();
    	    }
        },
    
        setCookie: function() { 
        	// console.log("generic.cart.setCookie "+this.totalItems);
        	var s  = {
        		totalItems: this.totalItems 
        	}
        	s = Object.toJSON(s);
        	generic.cookie("cart",s, {path:"/"}); 
        },
    
        getCart: function(args) {
            //console.log("generic.cart.getCart");
            var self = this; 

            if (args != null && args.pageDataKey) {
                var pageData = generic.page_data(args.pageDataKey);
                if (pageData.get("rpcdata")) {
                    console.log( "cart page data found!" );
                    self._updateCartData(pageData.get("rpcdata"));
                    return;
                }
            }

            var params = {};
            params = Object.extend ( params, self.transactionParams.transactionFields );
            params = Object.extend ( params, self.transactionParams.paymentFields);
            params = Object.extend ( params, self.transactionParams.orderFields);
        
             var id = generic.jsonrpc.fetch({
                method : 'trans.get',
                params: [params],
                onSuccess:function(jsonRpcResponse) {
                    self._updateCartData(jsonRpcResponse.getValue()); 
                },
                onFailure: function(jsonRpcResponse){
                	//jsonRpcResponse.getError();
                	console.log('Transaction JSON failed to load');
                }
            });
            return id;
        },
   
        //sets up internal representation of cart state
        // Assuming one order per transaction
        _updateCartData: function(data){ 
            // console.log("generic.checkout.cart._updateCartData");
            var self = this;
            this.data = data;
            this.totalItems = data.items_count; 
            this.defaultCartId = data.default_cart_id;
            this.payments = (data.trans && data.trans.payments) ? $A(data.trans.payments) : null;  
            this.order = data.order; 
         
            // contents and sample_contents mirror the sku by qty hashes
            this.order.contents = new Hash();
            this.order.sample_contents = new Hash();

            if (this.order.items != null) {
                this.order.items = this.order.items.reject(function(item){ // filter out nulls
                    return item === null;
                });
            }
        
            var items = this.order.items || null;
            var totalShoppedItems = 0;
            if (items != null) {  
                items.each(function(item){   
                    if (!item) { return; }
                    totalShoppedItems+=item.ITEM_QUANTITY;
                
                    // set up contents by cart hashes 
                    var cartID = item.CART_ID;
                    var cart = self.carts.get(cartID);
                    if (!cart) {
                        self.carts.set(cartID, new Hash()); 
                        cart = self.carts.get(cartID); 
                        cart.set('contents', new Hash());
                    } 
                    var id = item['sku.SKU_BASE_ID'] ? item['sku.SKU_BASE_ID'] : item.COLLECTION_ID; 
                    cart.get('contents').set(id, item.ITEM_QUANTITY);
                
                    // compute per-unit tax (replace this with field from JSONRPC result when available)
                    var unitTax = item.APPLIED_TAX/item.ITEM_QUANTITY;
                    item.UNIT_TAX = unitTax;

                    // set up order contents hash (spans carts)
                    if (item.itemType.toLowerCase() == 'skuitem') {
                        var key = item['sku.SKU_BASE_ID'];
                        var qty = item.ITEM_QUANTITY; 
                        //error self.order.contents.set(key, qty);
                        self.order.contents[key] = qty; 
                    } else if (item.itemType.toLowerCase() == 'kititem') {
                        var key = item.COLLECTION_ID;
                        var qty = item.ITEM_QUANTITY;
                        self.order.contents.set(key,qty);
                    } else {
                        // FUTURE: other cart item types (e.g. kits)
                    } 
                
                });
            }
        
            this.totalShoppedItems = totalShoppedItems;
        
            var samples = this.order.samples;
            if (samples != null) {
                samples.each(function(item){
                    // set up contents by cart hashes
                    var cartID = item.CART_ID;
                    var cart = self.carts.get(cartID);
                 
                    if (!cart) {
                        self.carts.set(cartID, new Hash());
                        cart = self.carts.get(cartID);
                        cart.set('contents', new Hash());
                    } 
               
                    var id = item['sku.SKU_BASE_ID'] ? item['sku.SKU_BASE_ID'] : item.COLLECTION_ID; 
                    cart.get('contents').set(id, item.ITEM_QUANTITY);

                    // set up order contents hash (spans carts)
                    if (item.itemType.toLowerCase() == 'sampleitem') {
                        var key = item['sku.SKU_BASE_ID'];
                        var qty = item.ITEM_QUANTITY;
                        self.order.sample_contents.set(key,qty); 
                    } else {
                        // other item types (are likely errors)
                    } 
                });
            }
        
            // if (self.setCookie) self.setCookie();
            generic.events.fire({event:'cart:countsUpdated'});
            // generic.events.fire({event:'cart:updated'}); 
        },
   
        /* args is a hash
        required keys: args.params.skus array, either args.params.INCREMENT or args.QTY with args.INCREMENT overriding args.QTY
        optional keys: args.itemType, args.OFFER_CODE, args.CART_ID*/ 
        updateCart: function(args) {
            // console.log("cart.updateCart: "+Object.toJSON(args.params));
            if (!args.params) return null; 

            var self = this;   
            var onSuccess = args.onSuccess || Prototype.emptyFunction;  
            var onFailure = args.onFailure || Prototype.emptyFunction; 
            var itemType = args.itemType || "product"; //e.g. product, collection, giftcard etc
            var id = self.itemTypes[itemType].id;
         
            var params = {
                '_SUBMIT': self.itemTypes[itemType]["_SUBMIT"] 
            };  
        
            //id 
            params[id] = (args.params.skus.length == 1) ? args.params.skus[0] : args.params.skus; //MK collections array syntax correct?
         
            //qty   
            if (args.params.INCREMENT && args.params.INCREMENT>=0) {
               //currently +1 will be added regardless of INCREMENT's actual value
               //backend requires QTY property to exist but it will not be used
         	 params["INCREMENT"] = args.params.INCREMENT; 
         	 params["QTY"] = 1; 
            } else if (args.params.INCREMENT && args.params.INCREMENT<0) {
            	//decrements qty by -1
            } else if (args.params.QTY && args.params.QTY>=0) { 
            	params["QTY"] = args.params.QTY;  
            }  
                     
            //offer code
            if (args.params.OFFER_CODE && args.params.OFFER_CODE.length>0) {
                params['OFFER_CODE'] = args.params.OFFER_CODE;
            }
            
            // targeting of the correct cart is still missing (and important to get right) 
            // cart id if we are adding to something other than the default cart
            if (args.params.cart_id && (args.params.cart_id != self.defaultCartId)) {
                params['CART_ID'] = args.params.cart_id;
            }
        
            var id = generic.jsonrpc.fetch({
                "method" : 'rpc.form',
                "params" : [params],
                "onSuccess": function(jsonRpcResponse){  
                    var data = jsonRpcResponse.getData();
                    //load data
                    if (data && data["trans_data"]) { 
                        self._updateCartData(data["trans_data"]);
                    }
                    var cartResultObj = new CartResult(data);
                    document.fire("cart:updated", cartResultObj);
                    onSuccess(jsonRpcResponse);
                },
                "onFailure": function(jsonRpcResponse){
                    onFailure(jsonRpcResponse);
                }
            });
 
            return id;
        }, 
    
        getItemQty : function(baseSkuId) {  
            if (!this.order.items) return 0;
            var lineItem = this.order.items.find( function (line) {
                return line['sku.SKU_BASE_ID'] ==  baseSkuId;
              });  
            if (!lineItem) {
                return 0; 
            }                
            return lineItem.ITEM_QUANTITY;
        },
    
        getBaseSkuIds: function() {  //MK: what is this used for?
            //console.log("generic.cart.getBaseSkuIds: "+this.order.items);
            if (!this.order.items) return new Hash();
            var baseSkuIds = this.order.items.pluck( 'sku.SKU_BASE_ID' ); //MK what about giftcards/collections?  
            return baseSkuIds; 
        },  
    
        getSubtotal: function() {
            var lineItems = this.order.items;
            if (!this.order.items) return 0;
            var subtotal = 0;
            for (var i=0, len = lineItems.length; i<len; i++) {
                var lineItem = lineItems[i];
                subtotal += (lineItem.UNIT_PRICE + lineItem.UNIT_TAX) * lineItem.ITEM_QUANTITY;
            }
            return subtotal;
        },
     
        getTotalShoppedItems: function(){ //products and gift cards
           /** var ttl = 0;
            var items = this.order.items;
            if (items != null) {
                items.each(function(item){
                    if (item && item.ITEM_QUANTITY) {
                        ttl += item.ITEM_QUANTITY;
                    }
                });
            } 
            return ttl;**/
            return this.totalShoppedItems;
        },         
        
        getTotalSamples: function() {
             var ttl = 0;
             var samples = this.order.samples;
                if (samples != null) {
                    samples.each(function(item){
                        ttl += item.ITEM_QUANTITY;
                    });
            } 
            return ttl;
        }, 
    
        getTotalItems: function(){ 
           // return this.getTotalShoppedItems() + this.getTotalSamples();
           return this.totalItems;
        },

        // Obtain address records associated with payments and orders (i.e., shipments).
        getPaymentAddresses: function(){
            debugger;
            var addresses;
            if (this.payments) {
                addresses = this.payments.pluck( 'address' );
            }
            return addresses;
        },

        // Caveat: Single-order transaction model is assumed.
        getOrderAddresses: function(){
            debugger;
            var addresses;
            if (this.order && this.order.address) {
                addresses = [];
                addresses.push(this.order.address);
            }
            return addresses;
        }
     };
}() ) ;
