/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *******************************************************************************/
package org.ofbiz.order.shoppingcart;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javolution.util.FastMap;

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.GeneralException;
import org.ofbiz.base.util.ObjectType;
import org.ofbiz.base.util.UtilHttp;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilNumber;
import org.ofbiz.base.util.UtilProperties;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.util.EntityUtil;
import org.ofbiz.order.order.OrderReadHelper;
import org.ofbiz.order.shoppingcart.product.ProductPromoWorker;
import org.ofbiz.product.config.ProductConfigWorker;
import org.ofbiz.product.config.ProductConfigWrapper;
import org.ofbiz.product.product.ProductWorker;
import org.ofbiz.security.Security;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.ModelService;
import org.ofbiz.service.ServiceUtil;

/**
 * A facade over the
 * {@link org.ofbiz.order.shoppingcart.ShoppingCart ShoppingCart}
 * providing catalog and product services to simplify the interaction
 * with the cart directly.
 */
public class ShoppingCartHelper {

    public static final String resource = "OrderUiLabels";
    public static String module = ShoppingCartHelper.class.getName();
    public static final String resource_error = "OrderErrorUiLabels";

    // The shopping cart to manipulate
    private ShoppingCart cart = null;

    // The entity engine delegator
    private Delegator delegator = null;

    // The service invoker
    private LocalDispatcher dispatcher = null;

    /**
     * Changes will be made to the cart directly, as opposed
     * to a copy of the cart provided.
     *
     * @param cart The cart to manipulate
     */
    public ShoppingCartHelper(Delegator delegator, LocalDispatcher dispatcher, ShoppingCart cart) {
        this.dispatcher = dispatcher;
        this.delegator = delegator;
        this.cart = cart;

        if (delegator == null) {
            this.delegator = dispatcher.getDelegator();
        }
        if (dispatcher == null) {
            throw new IllegalArgumentException("Dispatcher argument is null");
        }
        if (cart == null) {
            throw new IllegalArgumentException("ShoppingCart argument is null");
        }
    }

    /** Event to add an item to the shopping cart. */
    public Map<String, Object> addToCart(String catalogId, String shoppingListId, String shoppingListItemSeqId, String productId,
            String productCategoryId, String itemType, String itemDescription,
            BigDecimal price, BigDecimal amount, BigDecimal quantity,
            java.sql.Timestamp reservStart, BigDecimal reservLength, BigDecimal reservPersons,
            java.sql.Timestamp shipBeforeDate, java.sql.Timestamp shipAfterDate,
            ProductConfigWrapper configWrapper, String itemGroupNumber, Map<String, ? extends Object> context, String parentProductId) {

        return addToCart(catalogId,shoppingListId,shoppingListItemSeqId,productId,
                productCategoryId,itemType,itemDescription,price,amount,quantity,
                reservStart,reservLength,reservPersons,null,null,shipBeforeDate,shipAfterDate,
                configWrapper,itemGroupNumber,context,parentProductId);
    }

    /** Event to add an item to the shopping cart with accommodation. */
    public Map<String, Object> addToCart(String catalogId, String shoppingListId, String shoppingListItemSeqId, String productId,
            String productCategoryId, String itemType, String itemDescription,
            BigDecimal price, BigDecimal amount, BigDecimal quantity,
            java.sql.Timestamp reservStart, BigDecimal reservLength, BigDecimal reservPersons, String accommodationMapId,String accommodationSpotId,
            java.sql.Timestamp shipBeforeDate, java.sql.Timestamp shipAfterDate,
            ProductConfigWrapper configWrapper, String itemGroupNumber, Map<String, ? extends Object> context, String parentProductId) {
        Map<String, Object> result = null;
        Map<String, Object> attributes = null;
        String pProductId = null;
        pProductId = parentProductId;
        // price sanity check
        if (productId == null && price != null && price.compareTo(BigDecimal.ZERO) < 0) {
            String errMsg = UtilProperties.getMessage(resource_error, "cart.price_not_positive_number", this.cart.getLocale());
            result = ServiceUtil.returnError(errMsg);
            return result;
        }

        // quantity sanity check
        if (quantity.compareTo(BigDecimal.ONE) < 0) {
            String errMsg = UtilProperties.getMessage(resource_error, "cart.quantity_not_positive_number", this.cart.getLocale());
            result = ServiceUtil.returnError(errMsg);
            return result;
        }

        // amount sanity check
        if (amount != null && amount.compareTo(BigDecimal.ZERO) < 0) {
            String errMsg = UtilProperties.getMessage(resource_error, "cart.amount_not_positive_number", this.cart.getLocale());
            result = ServiceUtil.returnError(errMsg);
            return result;
        }

        // check desiredDeliveryDate syntax and remove if empty
        String ddDate = (String) context.get("itemDesiredDeliveryDate");
        if (!UtilValidate.isEmpty(ddDate)) {
            try {
                java.sql.Timestamp.valueOf((String) context.get("itemDesiredDeliveryDate"));
            } catch (IllegalArgumentException e) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resource_error,"OrderInvalidDesiredDeliveryDateSyntaxError",this.cart.getLocale()));
            }
        } else {
            context.remove("itemDesiredDeliveryDate");
        }

        // remove an empty comment
        String comment = (String) context.get("itemComment");
        if (UtilValidate.isEmpty(comment)) {
            context.remove("itemComment");
        }

        // stores the default desired delivery date in the cart if need
        if (!UtilValidate.isEmpty(context.get("useAsDefaultDesiredDeliveryDate"))) {
            cart.setDefaultItemDeliveryDate((String) context.get("itemDesiredDeliveryDate"));
        } else {
            // do we really want to clear this if it isn't checked?
            cart.setDefaultItemDeliveryDate(null);
        }

        // stores the default comment in session if need
        if (!UtilValidate.isEmpty(context.get("useAsDefaultComment"))) {
            cart.setDefaultItemComment((String) context.get("itemComment"));
        } else {
            // do we really want to clear this if it isn't checked?
            cart.setDefaultItemComment(null);
        }

        // Create a HashMap of product attributes - From ShoppingCartItem.attributeNames[]
        for (int namesIdx = 0; namesIdx < ShoppingCartItem.attributeNames.length; namesIdx++) {
            if (attributes == null)
                attributes = new HashMap<String, Object>();
            if (context.containsKey(ShoppingCartItem.attributeNames[namesIdx])) {
                attributes.put(ShoppingCartItem.attributeNames[namesIdx], context.get(ShoppingCartItem.attributeNames[namesIdx]));
            }
        }

        // check for required amount flag; if amount and no flag set to 0
        GenericValue product = null;
        if (productId != null) {
            try {
                product = delegator.findByPrimaryKeyCache("Product", UtilMisc.toMap("productId", productId));
            } catch (GenericEntityException e) {
                Debug.logError(e, "Unable to lookup product : " + productId, module);
            }
            if (product == null || product.get("requireAmount") == null || "N".equals(product.getString("requireAmount"))) {
                amount = null;
            }
            Debug.logInfo("carthelper productid " + productId,module);
            Debug.logInfo("parent productid " + pProductId,module);
            //if (product != null && !"Y".equals(product.getString("isVariant")))
            //    pProductId = null;

        }

        // Get the additional features selected for the product (if any)
        Map<String, Object> selectedFeatures = UtilHttp.makeParamMapWithPrefix(context, null, "FT", null);
        Iterator<String> selectedFeaturesTypes = selectedFeatures.keySet().iterator();
        Map<String, GenericValue> additionalFeaturesMap = FastMap.newInstance();
        while (selectedFeaturesTypes.hasNext()) {
            String selectedFeatureType = selectedFeaturesTypes.next();
            String selectedFeatureValue = (String)selectedFeatures.get(selectedFeatureType);
            if (UtilValidate.isNotEmpty(selectedFeatureValue)) {
                GenericValue productFeatureAndAppl = null;
                try {
                    productFeatureAndAppl = EntityUtil.getFirst(EntityUtil.filterByDate(delegator.findByAnd("ProductFeatureAndAppl",
                                                                                    UtilMisc.toMap("productId", productId,
                                                                                                   "productFeatureTypeId", selectedFeatureType,
                                                                                                   "productFeatureId", selectedFeatureValue))));
                } catch (GenericEntityException gee) {
                    Debug.logError(gee, module);
                }
                if (UtilValidate.isNotEmpty(productFeatureAndAppl)) {
                    productFeatureAndAppl.set("productFeatureApplTypeId", "STANDARD_FEATURE");
                }
                additionalFeaturesMap.put(selectedFeatureType, productFeatureAndAppl);
            }
        }

        // add or increase the item to the cart
        int itemId = -1;
        try {
            if (productId != null) {

                       itemId = cart.addOrIncreaseItem(productId, amount, quantity, reservStart, reservLength,
                                                reservPersons, accommodationMapId, accommodationSpotId, shipBeforeDate, shipAfterDate, additionalFeaturesMap, attributes,
                                                catalogId, configWrapper, itemType, itemGroupNumber, pProductId, dispatcher);

            } else {
                itemId = cart.addNonProductItem(itemType, itemDescription, productCategoryId, price, quantity, attributes, catalogId, itemGroupNumber, dispatcher);
            }

            // set the shopping list info
            if (itemId > -1 && shoppingListId != null && shoppingListItemSeqId != null) {
                ShoppingCartItem item = cart.findCartItem(itemId);
                item.setShoppingList(shoppingListId, shoppingListItemSeqId);
            }
        } catch (CartItemModifyException e) {
            if (cart.getOrderType().equals("PURCHASE_ORDER")) {
                String errMsg = UtilProperties.getMessage(resource_error, "cart.product_not_valid_for_supplier", this.cart.getLocale());
                errMsg = errMsg + " (" + e.getMessage() + ")";
                result = ServiceUtil.returnError(errMsg);
            } else {
                result = ServiceUtil.returnError(e.getMessage());
            }
            return result;
        } catch (ItemNotFoundException e) {
            result = ServiceUtil.returnError(e.getMessage());
            return result;
        }

        // Indicate there were no critical errors
        result = ServiceUtil.returnSuccess();
        if (itemId != -1) {
            result.put("itemId", new Integer(itemId));
        }
        return result;
    }

    public Map<String, Object> addToCartFromOrder(String catalogId, String orderId, String[] itemIds, boolean addAll, String itemGroupNumber) {
        ArrayList<String> errorMsgs = new ArrayList<String>();
        Map<String, Object> result;
        String errMsg = null;

        if (orderId == null || orderId.length() <= 0) {
            errMsg = UtilProperties.getMessage(resource_error,"cart.order_not_specified_to_add_from", this.cart.getLocale());
            result = ServiceUtil.returnError(errMsg);
            return result;
        }

        boolean noItems = true;
        List<? extends Object> itemIdList = null;
        Iterator<? extends Object> itemIter = null;
        OrderReadHelper orderHelper = new OrderReadHelper(delegator, orderId);
        if (addAll) {
            itemIdList = orderHelper.getOrderItems();
        } else {
            if (itemIds != null) {
                itemIdList = Arrays.asList(itemIds);
            }
        }
        if (UtilValidate.isNotEmpty(itemIdList)) {
            itemIter = itemIdList.iterator();
        }

        String orderItemTypeId = null;
        String productId = null;
        if (itemIter != null && itemIter.hasNext()) {
            while (itemIter.hasNext()) {
                GenericValue orderItem = null;
                Object value = itemIter.next();
                if (value instanceof GenericValue) {
                    orderItem = (GenericValue) value;
                } else {
                    String orderItemSeqId = (String) value;
                    orderItem = orderHelper.getOrderItem(orderItemSeqId);
                }
                orderItemTypeId = orderItem.getString("orderItemTypeId");
                productId = orderItem.getString("productId");
                // do not store rental items
                if (orderItemTypeId.equals("RENTAL_ORDER_ITEM"))
                    continue;
                // never read: int itemId = -1;
                if (UtilValidate.isNotEmpty(productId) && orderItem.get("quantity") != null) {
                    BigDecimal amount = orderItem.getBigDecimal("selectedAmount");
                    ProductConfigWrapper configWrapper = null;
                    String aggregatedProdId = null;
                    if ("AGGREGATED_CONF".equals(ProductWorker.getProductTypeId(delegator, productId))) {
                        try {
                            GenericValue instanceProduct = delegator.findByPrimaryKey("Product", UtilMisc.toMap("productId", productId));
                            String configId = instanceProduct.getString("configId");
                            aggregatedProdId = ProductWorker.getInstanceAggregatedId(delegator, productId);
                            configWrapper = ProductConfigWorker.loadProductConfigWrapper(delegator, dispatcher, configId, aggregatedProdId, cart.getProductStoreId(), catalogId, cart.getWebSiteId(), cart.getCurrency(), cart.getLocale(), cart.getAutoUserLogin());
                        } catch (GenericEntityException e) {
                            errorMsgs.add(e.getMessage());
                        }

                    }
                    try {
                        this.cart.addOrIncreaseItem(UtilValidate.isNotEmpty(aggregatedProdId) ? aggregatedProdId :  productId, amount, orderItem.getBigDecimal("quantity"),
                                null, null, null, null, null, null, null, catalogId, configWrapper, orderItemTypeId, itemGroupNumber, null, dispatcher);
                        noItems = false;
                    } catch (CartItemModifyException e) {
                        errorMsgs.add(e.getMessage());
                    } catch (ItemNotFoundException e) {
                        errorMsgs.add(e.getMessage());
                    }
                }
            }
            if (errorMsgs.size() > 0) {
                result = ServiceUtil.returnError(errorMsgs);
                result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
                return result; // don't return error because this is a non-critical error and should go back to the same page
            }
        } else {
            noItems = true;
        }

        if (noItems) {
            result = ServiceUtil.returnSuccess();
            result.put("_ERROR_MESSAGE_", UtilProperties.getMessage(resource_error,"OrderNoItemsFoundToAdd", this.cart.getLocale()));
            return result; // don't return error because this is a non-critical error and should go back to the same page
        }

        result = ServiceUtil.returnSuccess();
        return result;
    }

    /**
     * Adds all products in a category according to quantity request parameter
     * for each; if no parameter for a certain product in the category, or if
     * quantity is 0, do not add.
     * If a _ign_${itemGroupNumber} is appended to the name it will be put in that group instead of the default in the request parameter in itemGroupNumber
     *
     * There are 2 options for the syntax:
     *  - name="quantity_${productId}" value="${quantity}
     *  - name="product_${whatever}" value="${productId}" (note: quantity is always 1)
     */
    public Map<String, Object> addToCartBulk(String catalogId, String categoryId, Map<String, ? extends Object> context) {
        String itemGroupNumber = (String) context.get("itemGroupNumber");
        // use this prefix for the main structure such as a checkbox or a text input where name="quantity_${productId}" value="${quantity}"
        String keyPrefix = "quantity_";
        // use this prefix for a different structure, useful for radio buttons; can have any suffix, name="product_${whatever}" value="${productId}" and quantity is always 1
        String productQuantityKeyPrefix = "product_";

        // If a _ign_${itemGroupNumber} is appended to the name it will be put in that group instead of the default in the request parameter in itemGroupNumber
        String ignSeparator = "_ign_";

        // iterate through the context and find all keys that start with "quantity_"
        for (Map.Entry<String, ? extends Object> entry : context.entrySet()) {
            String productId = null;
            String quantStr = null;
            String itemGroupNumberToUse = itemGroupNumber;
            String originalProductId = null;
            if (entry.getKey() instanceof String) {
                String key = entry.getKey();
                //Debug.logInfo("Bulk Key: " + key, module);

                int ignIndex = key.indexOf(ignSeparator);
                if (ignIndex > 0) {
                    itemGroupNumberToUse = key.substring(ignIndex + ignSeparator.length());
                    key = key.substring(0, ignIndex);
                }

                if (key.startsWith(keyPrefix)) {
                    productId = key.substring(keyPrefix.length());
                    quantStr = (String) entry.getValue();
                } else if (key.startsWith(productQuantityKeyPrefix)) {
                    productId = (String) entry.getValue();
                    quantStr = "1";
                } else {
                    continue;
                }
            } else {
                continue;
            }

            if (UtilValidate.isNotEmpty(quantStr)) {
                BigDecimal quantity = BigDecimal.ZERO;

                try {
                    quantity = new BigDecimal(quantStr);
                } catch (NumberFormatException nfe) {
                    quantity = BigDecimal.ZERO;
                }
                if (quantity.compareTo(BigDecimal.ZERO) > 0) {
                    // check for alternative packing
                    if(ProductWorker.isAlternativePacking(delegator, null , productId)){
                        GenericValue originalProduct = null;
                        originalProductId = productId;
                        productId = ProductWorker.getOriginalProductId(delegator, productId);
                        try {
                            originalProduct = delegator.findByPrimaryKey("Product", UtilMisc.toMap("productId", originalProductId));
                        } catch (GenericEntityException e) {
                            Debug.logError(e, "Error getting parent product", module);
                        }
                        BigDecimal piecesIncluded = BigDecimal.ZERO;
                        if(originalProduct != null){
                            piecesIncluded = new BigDecimal(originalProduct.getLong("piecesIncluded"));
                            quantity = quantity.multiply(piecesIncluded);
                        }
                    }
                    
                    try {
                        if (Debug.verboseOn()) Debug.logVerbose("Bulk Adding to cart [" + quantity + "] of [" + productId + "] in Item Group [" + itemGroupNumber + "]", module);
                        this.cart.addOrIncreaseItem(productId, null, quantity, null, null, null, null, null, null, null, catalogId, null, null, itemGroupNumberToUse, originalProductId, dispatcher);
                    } catch (CartItemModifyException e) {
                        return ServiceUtil.returnError(e.getMessage());
                    } catch (ItemNotFoundException e) {
                        return ServiceUtil.returnError(e.getMessage());
                    }
                }
            }
        }

        //Indicate there were no non critical errors
        return ServiceUtil.returnSuccess();
    }

    /**
     * Adds a set of requirements to the cart.
     */
    public Map<String, Object> addToCartBulkRequirements(String catalogId, Map<String, ? extends Object> context) {
        String itemGroupNumber = (String) context.get("itemGroupNumber");
        // check if we are using per row submit
        boolean useRowSubmit = (!context.containsKey("_useRowSubmit"))? false :
                "Y".equalsIgnoreCase((String)context.get("_useRowSubmit"));

        // check if we are to also look in a global scope (no delimiter)
        //boolean checkGlobalScope = (!context.containsKey("_checkGlobalScope"))? false :
        //        "Y".equalsIgnoreCase((String)context.get("_checkGlobalScope"));

        // The number of multi form rows is retrieved
        int rowCount = UtilHttp.getMultiFormRowCount(context);

        // assume that the facility is the same for all requirements
        String facilityId = (String) context.get("facilityId_o_0");
        if (UtilValidate.isNotEmpty(facilityId)) {
            cart.setFacilityId(facilityId);
        }

        // now loop throw the rows and prepare/invoke the service for each
        for (int i = 0; i < rowCount; i++) {
            String productId = null;
            String quantStr = null;
            String requirementId = null;
            String thisSuffix = UtilHttp.MULTI_ROW_DELIMITER + i;
            boolean rowSelected = (!context.containsKey("_rowSubmit" + thisSuffix))? false :
                    "Y".equalsIgnoreCase((String)context.get("_rowSubmit" + thisSuffix));

            // make sure we are to process this row
            if (useRowSubmit && !rowSelected) {
                continue;
            }

            // build the context
            if (context.containsKey("productId" + thisSuffix)) {
                productId = (String) context.get("productId" + thisSuffix);
                quantStr = (String) context.get("quantity" + thisSuffix);
                requirementId = (String) context.get("requirementId" + thisSuffix);
                GenericValue requirement = null;
                try {
                    requirement = delegator.findByPrimaryKey("Requirement", UtilMisc.toMap("requirementId", requirementId));
                } catch (GenericEntityException gee) {
                }
                if (requirement == null) {
                    return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, 
                            "OrderRequirementDoesNotExists", 
                            UtilMisc.toMap("requirementId", requirementId), cart.getLocale()));
                }

                if (UtilValidate.isNotEmpty(quantStr)) {
                    BigDecimal quantity = BigDecimal.ZERO;
                    try {
                        quantity = (BigDecimal) ObjectType.simpleTypeConvert(quantStr, "BigDecimal", null, cart.getLocale());
                    } catch (GeneralException ge) {
                        quantity = BigDecimal.ZERO;
                    }
                    if (quantity.compareTo(BigDecimal.ZERO) > 0) {
                        Iterator<ShoppingCartItem> items = this.cart.iterator();
                        boolean requirementAlreadyInCart = false;
                        while (items.hasNext() && !requirementAlreadyInCart) {
                            ShoppingCartItem sci = items.next();
                            if (sci.getRequirementId() != null && sci.getRequirementId().equals(requirementId)) {
                                requirementAlreadyInCart = true;
                                continue;
                            }
                        }
                        if (requirementAlreadyInCart) {
                            if (Debug.warningOn()) Debug.logWarning(UtilProperties.getMessage(resource_error, "OrderTheRequirementIsAlreadyInTheCartNotAdding", UtilMisc.toMap("requirementId",requirementId), cart.getLocale()), module);
                            continue;
                        }
                        try {
                            if (Debug.verboseOn()) Debug.logVerbose("Bulk Adding to cart requirement [" + quantity + "] of [" + productId + "]", module);
                            int index = this.cart.addOrIncreaseItem(productId, null, quantity, null, null, null, requirement.getTimestamp("requiredByDate"), null, null, null, catalogId, null, null, itemGroupNumber, null, dispatcher);
                            ShoppingCartItem sci = this.cart.items().get(index);
                            sci.setRequirementId(requirementId);
                        } catch (CartItemModifyException e) {
                            return ServiceUtil.returnError(e.getMessage());
                        } catch (ItemNotFoundException e) {
                            return ServiceUtil.returnError(e.getMessage());
                        }
                    }
                }
            }
        }
        //Indicate there were no non critical errors
        return ServiceUtil.returnSuccess();
    }

    /**
     * Adds all products in a category according to default quantity on ProductCategoryMember
     * for each; if no default for a certain product in the category, or if
     * quantity is 0, do not add
     */
    public Map<String, Object> addCategoryDefaults(String catalogId, String categoryId, String itemGroupNumber) {
        ArrayList<String> errorMsgs = new ArrayList<String>();
        Map<String, Object> result = null;
        String errMsg = null;

        if (categoryId == null || categoryId.length() <= 0) {
            errMsg = UtilProperties.getMessage(resource_error,"cart.category_not_specified_to_add_from", this.cart.getLocale());
            result = ServiceUtil.returnError(errMsg);
            return result;
        }

        Collection<GenericValue> prodCatMemberCol = null;

        try {
            prodCatMemberCol = delegator.findByAndCache("ProductCategoryMember", UtilMisc.toMap("productCategoryId", categoryId));
        } catch (GenericEntityException e) {
            Debug.logWarning(e.toString(), module);
            Map<String, Object> messageMap = UtilMisc.<String, Object>toMap("categoryId", categoryId);
            messageMap.put("message", e.getMessage());
            errMsg = UtilProperties.getMessage(resource_error,"cart.could_not_get_products_in_category_cart", messageMap, this.cart.getLocale());
            result = ServiceUtil.returnError(errMsg);
            return result;
        }

        if (prodCatMemberCol == null) {
            Map<String, Object> messageMap = UtilMisc.<String, Object>toMap("categoryId", categoryId);
            errMsg = UtilProperties.getMessage(resource_error,"cart.could_not_get_products_in_category", messageMap, this.cart.getLocale());
            result = ServiceUtil.returnError(errMsg);
            return result;
        }

        BigDecimal totalQuantity = BigDecimal.ZERO;
        Iterator<GenericValue> pcmIter = prodCatMemberCol.iterator();

        while (pcmIter.hasNext()) {
            GenericValue productCategoryMember = pcmIter.next();
            BigDecimal quantity = productCategoryMember.getBigDecimal("quantity");

            if (quantity != null && quantity.compareTo(BigDecimal.ZERO) > 0) {
                try {
                    this.cart.addOrIncreaseItem(productCategoryMember.getString("productId"),
                            null, quantity, null, null, null, null, null, null, null,
                            catalogId, null, null, itemGroupNumber, null, dispatcher);
                    totalQuantity = totalQuantity.add(quantity);
                } catch (CartItemModifyException e) {
                    errorMsgs.add(e.getMessage());
                } catch (ItemNotFoundException e) {
                    errorMsgs.add(e.getMessage());
                }
            }
        }
        if (errorMsgs.size() > 0) {
            result = ServiceUtil.returnError(errorMsgs);
            result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
            return result; // don't return error because this is a non-critical error and should go back to the same page
        }

        result = ServiceUtil.returnSuccess();
        result.put("totalQuantity", totalQuantity);
        return result;
    }

    /** Delete an item from the shopping cart. */
    public Map<String, Object> deleteFromCart(Map<String, ? extends Object> context) {
        Map<String, Object> result = null;
        Set<String> names = context.keySet();
        Iterator<String> i = names.iterator();
        ArrayList<String> errorMsgs = new ArrayList<String>();

        while (i.hasNext()) {
            String o = i.next();

            if (o.toUpperCase().startsWith("DELETE")) {
                try {
                    String indexStr = o.substring(o.lastIndexOf('_') + 1);
                    int index = Integer.parseInt(indexStr);

                    try {
                        this.cart.removeCartItem(index, dispatcher);
                    } catch (CartItemModifyException e) {
                        errorMsgs.add(e.getMessage());
                    }
                } catch (NumberFormatException nfe) {}
            }
        }

        if (errorMsgs.size() > 0) {
            result = ServiceUtil.returnError(errorMsgs);
            result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
            return result; // don't return error because this is a non-critical error and should go back to the same page
        }

        result = ServiceUtil.returnSuccess();
        return result;
    }

    /** Update the items in the shopping cart. */
    public Map<String, Object> modifyCart(Security security, GenericValue userLogin, Map<String, ? extends Object> context, boolean removeSelected, String[] selectedItems, Locale locale) {
        Map<String, Object> result = null;
        if (locale == null) {
            locale = this.cart.getLocale();
        }

        ArrayList<ShoppingCartItem> deleteList = new ArrayList<ShoppingCartItem>();
        ArrayList<String> errorMsgs = new ArrayList<String>();

        Set<String> parameterNames = context.keySet();
        Iterator<String> parameterNameIter = parameterNames.iterator();

        BigDecimal oldQuantity = BigDecimal.ONE.negate();
        String oldDescription = "";
        BigDecimal oldPrice = BigDecimal.ONE.negate();

        if (this.cart.isReadOnlyCart()) {
            String errMsg = UtilProperties.getMessage(resource_error, "cart.cart_is_in_read_only_mode", this.cart.getLocale());
            errorMsgs.add(errMsg);
            result = ServiceUtil.returnError(errorMsgs);
            return result;
        }

        // TODO: This should be refactored to use UtilHttp.parseMultiFormData(parameters)
        while (parameterNameIter.hasNext()) {
            String parameterName = parameterNameIter.next();
            int underscorePos = parameterName.lastIndexOf('_');

            if (underscorePos >= 0) {
                try {
                    String indexStr = parameterName.substring(underscorePos + 1);
                    int index = Integer.parseInt(indexStr);
                    String quantString = (String) context.get(parameterName);
                    BigDecimal quantity = BigDecimal.ONE.negate();
                    String itemDescription = "";
                    if (quantString != null) quantString = quantString.trim();

                    // get the cart item
                    ShoppingCartItem item = this.cart.findCartItem(index);
                    if (parameterName.toUpperCase().startsWith("OPTION")) {
                        if (quantString.toUpperCase().startsWith("NO^")) {
                            if (quantString.length() > 2) { // the length of the prefix
                                String featureTypeId = this.getRemoveFeatureTypeId(parameterName);
                                if (featureTypeId != null) {
                                    item.removeAdditionalProductFeatureAndAppl(featureTypeId);
                                }
                            }
                        } else {
                            GenericValue featureAppl = this.getFeatureAppl(item.getProductId(), parameterName, quantString);
                            if (featureAppl != null) {
                                item.putAdditionalProductFeatureAndAppl(featureAppl);
                            }
                        }
                    } else if (parameterName.toUpperCase().startsWith("DESCRIPTION")) {
                        itemDescription = quantString;  // the quantString is actually the description if the field name starts with DESCRIPTION
                    } else if (parameterName.startsWith("reservStart")) {
                        if (quantString.length() ==0) {
                            // should have format: yyyy-mm-dd hh:mm:ss.fffffffff
                            quantString += " 00:00:00.000000000";
                        }
                        if (item != null) {
                            Timestamp reservStart = Timestamp.valueOf(quantString);
                            item.setReservStart(reservStart);
                        }
                    } else if (parameterName.startsWith("reservLength")) {
                        if (item != null) {
                            BigDecimal reservLength = (BigDecimal) ObjectType.simpleTypeConvert(quantString, "BigDecimal", null, locale);
                            item.setReservLength(reservLength);
                        }
                    } else if (parameterName.startsWith("reservPersons")) {
                        if (item != null) {
                            BigDecimal reservPersons = (BigDecimal) ObjectType.simpleTypeConvert(quantString, "BigDecimal", null, locale);
                            item.setReservPersons(reservPersons);
                        }
                    } else if (parameterName.startsWith("shipBeforeDate")) {
                        if (UtilValidate.isNotEmpty(quantString)) {
                            // input is either yyyy-mm-dd or a full timestamp
                            if (quantString.length() == 10)
                                quantString += " 00:00:00.000";
                            item.setShipBeforeDate(Timestamp.valueOf(quantString));
                        }
                    } else if (parameterName.startsWith("shipAfterDate")) {
                        if (UtilValidate.isNotEmpty(quantString)) {
                            // input is either yyyy-mm-dd or a full timestamp
                            if (quantString.length() == 10)
                                quantString += " 00:00:00.000";
                            item.setShipAfterDate(Timestamp.valueOf(quantString));
                        }
                    } else if (parameterName.startsWith("amount")) {
                        if (UtilValidate.isNotEmpty(quantString)) {
                            BigDecimal amount = new BigDecimal(quantString);
                            if (amount.compareTo(BigDecimal.ZERO) <= 0) {
                                String errMsg = UtilProperties.getMessage(resource_error, "cart.amount_not_positive_number", this.cart.getLocale());
                                errorMsgs.add(errMsg);
                                result = ServiceUtil.returnError(errorMsgs);
                                return result;
                            }
                            item.setSelectedAmount(amount);
                        }
                    } else if (parameterName.startsWith("itemType")) {
                        if (UtilValidate.isNotEmpty(quantString)) {
                            item.setItemType(quantString);
                        }
                    } else {
                        quantity = (BigDecimal) ObjectType.simpleTypeConvert(quantString, "BigDecimal", null, locale);
                        //For quantity we should test if we allow to add decimal quantity for this product an productStore : if not then round to 0
                        if(! ProductWorker.isDecimalQuantityOrderAllowed(delegator, item.getProductId(), cart.getProductStoreId())){
                            quantity = quantity.setScale(0, UtilNumber.getBigDecimalRoundingMode("order.rounding"));
                        }                
                        else {
                            quantity = quantity.setScale(UtilNumber.getBigDecimalScale("order.decimals"), UtilNumber.getBigDecimalRoundingMode("order.rounding"));
                        }
                        if (quantity.compareTo(BigDecimal.ZERO) < 0) {
                            String errMsg = UtilProperties.getMessage(resource_error, "cart.quantity_not_positive_number", this.cart.getLocale());
                            errorMsgs.add(errMsg);
                            result = ServiceUtil.returnError(errorMsgs);
                            return result;
                        }
                    }

                    // perhaps we need to reset the ship groups' before and after dates based on new dates for the items
                    if (parameterName.startsWith("shipAfterDate") || parameterName.startsWith("shipBeforeDate")) {
                        this.cart.setShipGroupShipDatesFromItem(item);
                    }

                    if (parameterName.toUpperCase().startsWith("UPDATE")) {
                        if (quantity.compareTo(BigDecimal.ZERO) == 0) {
                            deleteList.add(item);
                        } else {
                            if (item != null) {
                                try {
                                    // if, on a purchase order, the quantity has changed, get the new SupplierProduct entity for this quantity level.
                                    if (cart.getOrderType().equals("PURCHASE_ORDER")) {
                                        oldQuantity = item.getQuantity();
                                        if (oldQuantity.compareTo(quantity) != 0) {
                                            // save the old description and price, in case the user wants to change those as well
                                            oldDescription = item.getName();
                                            oldPrice = item.getBasePrice();


                                            GenericValue supplierProduct = this.cart.getSupplierProduct(item.getProductId(), quantity, this.dispatcher);

                                            if (supplierProduct == null) {
                                                if ("_NA_".equals(cart.getPartyId())) {
                                                    // no supplier does not require the supplier product
                                                    item.setQuantity(quantity, dispatcher, this.cart);
                                                    item.setName(item.getProduct().getString("internalName"));
                                                } else {
                                                    // in this case, the user wanted to purchase a quantity which is not available (probably below minimum)
                                                    String errMsg = UtilProperties.getMessage(resource_error, "cart.product_not_valid_for_supplier", this.cart.getLocale());
                                                    errMsg = errMsg + " (" + item.getProductId() + ", " + quantity + ", " + cart.getCurrency() + ")";
                                                    errorMsgs.add(errMsg);
                                                }
                                            } else {
                                                item.setSupplierProductId(supplierProduct.getString("supplierProductId"));
                                                item.setQuantity(quantity, dispatcher, this.cart);
                                                item.setBasePrice(supplierProduct.getBigDecimal("lastPrice"));
                                                item.setName(ShoppingCartItem.getPurchaseOrderItemDescription(item.getProduct(), supplierProduct, cart.getLocale()));
                                            }
                                        }
                                    } else {
                                        BigDecimal minQuantity = ShoppingCart.getMinimumOrderQuantity(delegator, item.getBasePrice(), item.getProductId());
                                        if (quantity.compareTo(minQuantity) < 0) {
                                            quantity = minQuantity;
                                        }
                                        item.setQuantity(quantity, dispatcher, this.cart, true, false);
                                        cart.setItemShipGroupQty(item, quantity, 0);
                                    }
                                } catch (CartItemModifyException e) {
                                    errorMsgs.add(e.getMessage());
                                }
                            }
                        }
                    }

                    if (parameterName.toUpperCase().startsWith("DESCRIPTION")) {
                        if (!oldDescription.equals(itemDescription)) {
                            if (security.hasEntityPermission("ORDERMGR", "_CREATE", userLogin)) {
                                if (item != null) {
                                    item.setName(itemDescription);
                                }
                            }
                        }
                    }

                    if (parameterName.toUpperCase().startsWith("PRICE")) {
                        NumberFormat pf = NumberFormat.getCurrencyInstance(locale);
                        String tmpQuantity = pf.format(quantity);
                        String tmpOldPrice = pf.format(oldPrice);
                        if (!tmpOldPrice.equals(tmpQuantity)) {
                            if (security.hasEntityPermission("ORDERMGR", "_CREATE", userLogin)) {
                                if (item != null) {
                                    item.setBasePrice(quantity); // this is quantity because the parsed number variable is the same as quantity
                                    item.setDisplayPrice(quantity); // or the amount shown the cart items page won't be right
                                    item.setIsModifiedPrice(true); // flag as a modified price
                                }
                            }
                        }
                    }

                    if (parameterName.toUpperCase().startsWith("DELETE")) {
                        deleteList.add(this.cart.findCartItem(index));
                    }
                } catch (NumberFormatException nfe) {
                    Debug.logWarning(nfe, UtilProperties.getMessage(resource_error, "OrderCaughtNumberFormatExceptionOnCartUpdate", cart.getLocale()));
                } catch (Exception e) {
                    Debug.logWarning(e, UtilProperties.getMessage(resource_error, "OrderCaughtExceptionOnCartUpdate", cart.getLocale()));
                }
            } // else not a parameter we need
        }

        // get a list of the items to delete
        if (removeSelected) {
            for (int si = 0; si < selectedItems.length; si++) {
                String indexStr = selectedItems[si];
                ShoppingCartItem item = null;
                try {
                    int index = Integer.parseInt(indexStr);
                    item = this.cart.findCartItem(index);
                } catch (Exception e) {
                    Debug.logWarning(e, UtilProperties.getMessage(resource_error, "OrderProblemsGettingTheCartItemByIndex", cart.getLocale()));
                }
                if (item != null) {
                    deleteList.add(item);
                }
            }
        }

        Iterator<ShoppingCartItem> di = deleteList.iterator();

        while (di.hasNext()) {
            ShoppingCartItem item = di.next();
            int itemIndex = this.cart.getItemIndex(item);

            if (Debug.infoOn())
                Debug.logInfo("Removing item index: " + itemIndex, module);
            try {
                this.cart.removeCartItem(itemIndex, dispatcher);
            } catch (CartItemModifyException e) {
                result = ServiceUtil.returnError(new ArrayList<String>());
                errorMsgs.add(e.getMessage());
            }
        }

        if (context.containsKey("alwaysShowcart")) {
            this.cart.setViewCartOnAdd(true);
        } else {
            this.cart.setViewCartOnAdd(false);
        }

        // Promotions are run again.
        ProductPromoWorker.doPromotions(this.cart, dispatcher);

        if (errorMsgs.size() > 0) {
            result = ServiceUtil.returnError(errorMsgs);
            return result;
        }

        result = ServiceUtil.returnSuccess();
        return result;
    }

    /** Empty the shopping cart. */
    public boolean clearCart() {
        this.cart.clear();
        return true;
    }

    /** Returns the shopping cart this helper is wrapping. */
    public ShoppingCart getCartObject() {
        return this.cart;
    }

    public GenericValue getFeatureAppl(String productId, String optionField, String featureId) {
        if (delegator == null) {
            throw new IllegalArgumentException("No delegator available to lookup ProductFeature");
        }

        Map<String, String> fields = UtilMisc.<String, String>toMap("productId", productId, "productFeatureId", featureId);
        if (optionField != null) {
            int featureTypeStartIndex = optionField.indexOf('^') + 1;
            int featureTypeEndIndex = optionField.lastIndexOf('_');
            if (featureTypeStartIndex > 0 && featureTypeEndIndex > 0) {
                fields.put("productFeatureTypeId", optionField.substring(featureTypeStartIndex, featureTypeEndIndex));
            }
        }

        GenericValue productFeatureAppl = null;
        List<GenericValue> features = null;
        try {
            features = delegator.findByAnd("ProductFeatureAndAppl", fields, UtilMisc.toList("-fromDate"));
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return null;
        }

        if (features != null) {
            if (features.size() > 1) {
                features = EntityUtil.filterByDate(features);
            }
            productFeatureAppl = EntityUtil.getFirst(features);
        }

        return productFeatureAppl;
    }

    public String getRemoveFeatureTypeId(String optionField) {
        if (optionField != null) {
            int featureTypeStartIndex = optionField.indexOf('^') + 1;
            int featureTypeEndIndex = optionField.lastIndexOf('_');
            if (featureTypeStartIndex > 0 && featureTypeEndIndex > 0) {
                return optionField.substring(featureTypeStartIndex, featureTypeEndIndex);
            }
        }
        return null;
    }
    /**
     * Select an agreement
     *
     * @param agreementId
     */
    public Map<String, Object> selectAgreement(String agreementId) {
        Map<String, Object> result = null;
        GenericValue agreement = null;

        if ((this.delegator == null) || (this.dispatcher == null) || (this.cart == null)) {
            result = ServiceUtil.returnError(UtilProperties.getMessage(resource_error,"OrderDispatcherOrDelegatorOrCartArgumentIsNull",this.cart.getLocale()));
            return result;
        }

        if ((agreementId == null) || (agreementId.length() <= 0)) {
            result = ServiceUtil.returnError(UtilProperties.getMessage(resource_error,"OrderNoAgreementSpecified",this.cart.getLocale()));
            return result;
        }

        try {
            agreement = this.delegator.findByPrimaryKeyCache("Agreement",UtilMisc.toMap("agreementId", agreementId));
        } catch (GenericEntityException e) {
            Debug.logWarning(e.toString(), module);
            result = ServiceUtil.returnError(UtilProperties.getMessage(resource_error,"OrderCouldNotGetAgreement",UtilMisc.toMap("agreementId",agreementId),this.cart.getLocale()) + UtilProperties.getMessage(resource_error,"OrderError",this.cart.getLocale()) + e.getMessage());
            return result;
        }

        if (agreement == null) {
            result = ServiceUtil.returnError(UtilProperties.getMessage(resource_error,"OrderCouldNotGetAgreement",UtilMisc.toMap("agreementId",agreementId),this.cart.getLocale()));
        } else {
            // set the agreement id in the cart
            cart.setAgreementId(agreementId);
            try {
                // set the currency based on the pricing agreement
                List<GenericValue> agreementItems = agreement.getRelated("AgreementItem", UtilMisc.toMap("agreementItemTypeId", "AGREEMENT_PRICING_PR"), null);
                if (agreementItems.size() > 0) {
                    GenericValue agreementItem = agreementItems.get(0);
                    String currencyUomId = (String) agreementItem.get("currencyUomId");
                    if (UtilValidate.isNotEmpty(currencyUomId)) {
                        try {
                            cart.setCurrency(dispatcher,currencyUomId);
                        } catch (CartItemModifyException ex) {
                            result = ServiceUtil.returnError(UtilProperties.getMessage(resource_error,"OrderSetCurrencyError",this.cart.getLocale()) + ex.getMessage());
                            return result;
                        }
                    }
                }
            } catch (GenericEntityException e) {
                Debug.logWarning(e.toString(), module);
                result = ServiceUtil.returnError(UtilProperties.getMessage(resource_error,"OrderCouldNotGetAgreementItemsThrough",UtilMisc.toMap("agreementId",agreementId),this.cart.getLocale()) + UtilProperties.getMessage(resource_error,"OrderError",this.cart.getLocale()) + e.getMessage());
                return result;
            }

            try {
                 // clear the existing order terms
                 cart.removeOrderTerms();
                 // set order terms based on agreement terms
                 List<GenericValue> agreementTerms = EntityUtil.filterByDate(agreement.getRelated("AgreementTerm"));
                 if (agreementTerms.size() > 0) {
                      for (int i = 0; agreementTerms.size() > i;i++) {
                           GenericValue agreementTerm = agreementTerms.get(i);
                           String termTypeId = (String) agreementTerm.get("termTypeId");
                           BigDecimal termValue = agreementTerm.getBigDecimal("termValue");
                           Long termDays = (Long) agreementTerm.get("termDays");
                           String textValue = agreementTerm.getString("textValue");
                           cart.addOrderTerm(termTypeId, termValue, termDays, textValue);
                      }
                  }
            } catch (GenericEntityException e) {
                  Debug.logWarning(e.toString(), module);
                  result = ServiceUtil.returnError(UtilProperties.getMessage(resource_error,"OrderCouldNotGetAgreementTermsThrough",UtilMisc.toMap("agreementId",agreementId),this.cart.getLocale())  + UtilProperties.getMessage(resource_error,"OrderError",this.cart.getLocale()) + e.getMessage());
                  return result;
            }
        }
        return result;
    }

    public Map<String, Object> setCurrency(String currencyUomId) {
        Map<String, Object> result = null;

        try {
            this.cart.setCurrency(this.dispatcher,currencyUomId);
            result = ServiceUtil.returnSuccess();
         } catch (CartItemModifyException ex) {
             result = ServiceUtil.returnError(UtilProperties.getMessage(resource_error,"OrderSetCurrencyError",this.cart.getLocale()) + ex.getMessage());
             return result;
         }
        return result;
    }

    public Map<String, Object> addOrderTerm(String termTypeId, BigDecimal termValue, Long termDays) {
        return addOrderTerm(termTypeId, termValue, termDays, null);
    }

    public Map<String, Object> addOrderTerm(String termTypeId, BigDecimal termValue,Long termDays, String textValue) {
        Map<String, Object> result = null;
        this.cart.addOrderTerm(termTypeId,termValue,termDays,textValue);
        result = ServiceUtil.returnSuccess();
        return result;
    }

    public Map<String, Object> removeOrderTerm(int index) {
        Map<String, Object> result = null;
        this.cart.removeOrderTerm(index);
        result = ServiceUtil.returnSuccess();
        return result;
    }

}
