/*******************************************************************************
 * 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.product;

import java.math.BigDecimal;
import java.math.MathContext;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;

import javolution.util.FastList;
import javolution.util.FastMap;

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilNumber;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntity;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.util.EntityUtil;
import org.ofbiz.order.shoppingcart.ShoppingCart;
import org.ofbiz.order.shoppingcart.ShoppingCartItem;
import org.ofbiz.product.catalog.CatalogWorker;
import org.ofbiz.product.category.CategoryWorker;
import org.ofbiz.product.product.ProductWorker;


public class ProductDisplayWorker {

    public static final String module = ProductDisplayWorker.class.getName();

    /* ========================================================================================*/

    /* ============================= Special Data Retrieval Methods ===========================*/

    public static List<GenericValue> getRandomCartProductAssoc(ServletRequest request, boolean checkViewAllow) {
        Delegator delegator = (Delegator) request.getAttribute("delegator");
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        ShoppingCart cart = (ShoppingCart) httpRequest.getSession().getAttribute("shoppingCart");

        if (cart == null || cart.size() <= 0) return null;

        List<GenericValue> cartAssocs = null;
        try {
            Map<String, GenericValue> products = FastMap.newInstance();

            Iterator<ShoppingCartItem> cartiter = cart.iterator();

            while (cartiter != null && cartiter.hasNext()) {
                ShoppingCartItem item = cartiter.next();
                // Collection upgradeProducts = delegator.findByAndCache("ProductAssoc", UtilMisc.toMap("productId", item.getProductId(), "productAssocTypeId", "PRODUCT_UPGRADE"), null);
                List<GenericValue> complementProducts = delegator.findByAndCache("ProductAssoc", UtilMisc.toMap("productId", item.getProductId(), "productAssocTypeId", "PRODUCT_COMPLEMENT"), null);
                // since ProductAssoc records have a fromDate and thruDate, we can filter by now so that only assocs in the date range are included
                complementProducts = EntityUtil.filterByDate(complementProducts);

                List<GenericValue> productsCategories = delegator.findByAndCache("ProductCategoryMember", UtilMisc.toMap("productId", item.getProductId()), null);
                productsCategories = EntityUtil.filterByDate(productsCategories, true);
                if (productsCategories != null) {
                    Iterator<GenericValue> productsCategoriesIter = productsCategories.iterator();
                    while (productsCategoriesIter.hasNext()) {
                        GenericValue productsCategoryMember = productsCategoriesIter.next();
                        GenericValue productsCategory = productsCategoryMember.getRelatedOneCache("ProductCategory");
                        if ("CROSS_SELL_CATEGORY".equals(productsCategory.getString("productCategoryTypeId"))) {
                            List<GenericValue> curPcms = productsCategory.getRelatedCache("ProductCategoryMember");
                            if (curPcms != null) {
                                Iterator<GenericValue> curPcmsIter = curPcms.iterator();
                                while (curPcmsIter.hasNext()) {
                                    GenericValue curPcm = curPcmsIter.next();
                                    if (!products.containsKey(curPcm.getString("productId"))) {
                                        GenericValue product = curPcm.getRelatedOneCache("Product");
                                        products.put(product.getString("productId"), product);
                                    }
                                }
                            }
                        }
                    }
                }

                if (UtilValidate.isNotEmpty(complementProducts)) {
                    Iterator<GenericValue> complIter = complementProducts.iterator();
                    while (complIter.hasNext()) {
                        GenericValue productAssoc = complIter.next();
                        if (!products.containsKey(productAssoc.getString("productIdTo"))) {
                            GenericValue product = productAssoc.getRelatedOneCache("AssocProduct");
                            products.put(product.getString("productId"), product);
                        }
                    }
                }
            }

            // remove all products that are already in the cart
            cartiter = cart.iterator();
            while (cartiter != null && cartiter.hasNext()) {
                ShoppingCartItem item = cartiter.next();
                products.remove(item.getProductId());
            }

            // if desired check view allow category
            if (checkViewAllow) {
                String currentCatalogId = CatalogWorker.getCurrentCatalogId(request);
                String viewProductCategoryId = CatalogWorker.getCatalogViewAllowCategoryId(delegator, currentCatalogId);
                if (viewProductCategoryId != null) {
                    List<GenericValue> tempList = FastList.newInstance();
                    tempList.addAll(products.values());
                    tempList = CategoryWorker.filterProductsInCategory(delegator, tempList, viewProductCategoryId, "productId");
                    cartAssocs = FastList.newInstance();
                    cartAssocs.addAll(tempList);
                }
            }

            if (cartAssocs == null) {
                cartAssocs = FastList.newInstance();
                cartAssocs.addAll(products.values());
            }

            // randomly remove products while there are more than 3
            while (cartAssocs.size() > 3) {
                int toRemove = (int) (Math.random() *  cartAssocs.size());
                cartAssocs.remove(toRemove);
            }
        } catch (GenericEntityException e) {
            Debug.logWarning(e, module);
        }

        if (UtilValidate.isNotEmpty(cartAssocs)) {
            return cartAssocs;
        } else {
            return null;
        }
    }

    public static Map<String, Object> getQuickReorderProducts(ServletRequest request) {
        Delegator delegator = (Delegator) request.getAttribute("delegator");
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        GenericValue userLogin = (GenericValue) httpRequest.getSession().getAttribute("userLogin");
        Map<String, Object> results = FastMap.newInstance();

        if (userLogin == null) userLogin = (GenericValue) httpRequest.getSession().getAttribute("autoUserLogin");
        if (userLogin == null) return results;

        try {
            Map<String, GenericValue> products = UtilGenerics.checkMap(httpRequest.getSession().getAttribute("_QUICK_REORDER_PRODUCTS_"));
            Map<String, BigDecimal> productQuantities = UtilGenerics.checkMap(httpRequest.getSession().getAttribute("_QUICK_REORDER_PRODUCT_QUANTITIES_"));
            Map<String, Integer> productOccurances = UtilGenerics.checkMap(httpRequest.getSession().getAttribute("_QUICK_REORDER_PRODUCT_OCCURANCES_"));

            if (products == null || productQuantities == null || productOccurances == null) {
                products = new HashMap<String, GenericValue>();
                productQuantities = new HashMap<String, BigDecimal>();
                // keep track of how many times a product occurs in order to find averages and rank by purchase amount
                productOccurances = new HashMap<String, Integer>();
                
                // get all order role entities for user by customer role type
                // final String[] USER_ORDER_ROLE_TYPES = {"END_USER_CUSTOMER", "SHIP_TO_CUSTOMER", "BILL_TO_CUSTOMER", "PLACING_CUSTOMER"};
                final String[] USER_ORDER_ROLE_TYPES = {"PLACING_CUSTOMER"};

                for (int i = 0; i < USER_ORDER_ROLE_TYPES.length; i++) {
                    List<GenericValue> orderRoles = delegator.findByAnd("OrderRole", UtilMisc.toMap("partyId", userLogin.get("partyId"), "roleTypeId", USER_ORDER_ROLE_TYPES[i]), null);
                    Iterator<GenericValue> ordersIter = UtilMisc.toIterator(orderRoles);

                    while (ordersIter != null && ordersIter.hasNext()) {
                        GenericValue orderRole = ordersIter.next();
                        // for each order role get all order items
                        List<GenericValue> orderItems = orderRole.getRelated("OrderItem");
                        Iterator<GenericValue> orderItemsIter = UtilMisc.toIterator(orderItems);

                        while (orderItemsIter != null && orderItemsIter.hasNext()) {
                            GenericValue orderItem = orderItemsIter.next();
                            String productId = orderItem.getString("productId");
                            if (UtilValidate.isNotEmpty(productId)) {
                                // for each order item get the associated product
                                GenericValue product = orderItem.getRelatedOneCache("Product");

                                products.put(product.getString("productId"), product);

                                BigDecimal curQuant = productQuantities.get(product.get("productId"));

                                if (curQuant == null) curQuant = BigDecimal.ZERO;
                                BigDecimal orderQuant = orderItem.getBigDecimal("quantity");

                                if (orderQuant == null) orderQuant = BigDecimal.ZERO;
                                productQuantities.put(product.getString("productId"), curQuant.add(orderQuant));

                                Integer curOcc = productOccurances.get(product.get("productId"));

                                if (curOcc == null) curOcc = Integer.valueOf(0);
                                productOccurances.put(product.getString("productId"), Integer.valueOf(curOcc.intValue() + 1));
                            }
                        }
                    }
                }

                // go through each product quantity and divide it by the occurances to get the average
                for (Map.Entry<String, BigDecimal> entry : productQuantities.entrySet()) {
                    String prodId = entry.getKey();
                    BigDecimal quantity = entry.getValue();
                    Integer occs = productOccurances.get(prodId);
                    BigDecimal nqint = quantity.divide(new BigDecimal(occs), new MathContext(10));

                    if (nqint.compareTo(BigDecimal.ONE) < 0) nqint = BigDecimal.ONE;
                    productQuantities.put(prodId, nqint);
                }
                
                httpRequest.getSession().setAttribute("_QUICK_REORDER_PRODUCTS_", new HashMap<String, GenericValue>(products));
                httpRequest.getSession().setAttribute("_QUICK_REORDER_PRODUCT_QUANTITIES_", new HashMap<String, BigDecimal>(productQuantities));
                httpRequest.getSession().setAttribute("_QUICK_REORDER_PRODUCT_OCCURANCES_", new HashMap<String, Integer>(productOccurances));
            } else {
                // make a copy since we are going to change them
                products = new HashMap<String, GenericValue>(products);
                productQuantities = new HashMap<String, BigDecimal>(productQuantities);
                productOccurances = new HashMap<String, Integer>(productOccurances);
            }

            // remove all products that are already in the cart
            ShoppingCart cart = (ShoppingCart) httpRequest.getSession().getAttribute("shoppingCart");
            if (UtilValidate.isNotEmpty(cart)) {
                Iterator<ShoppingCartItem> cartiter = cart.iterator();
                while (cartiter.hasNext()) {
                    ShoppingCartItem item = cartiter.next();
                    String productId = item.getProductId();
                    products.remove(productId);
                    productQuantities.remove(productId);
                    productOccurances.remove(productId);
                }
            }

            // if desired check view allow category
            //if (checkViewAllow) {
                //Set prodKeySet = products.keySet();
                String currentCatalogId = CatalogWorker.getCurrentCatalogId(request);
                String viewProductCategoryId = CatalogWorker.getCatalogViewAllowCategoryId(delegator, currentCatalogId);
                if (viewProductCategoryId != null) {
                    for (Map.Entry<String, GenericValue> entry : products.entrySet()) {
                        String productId = entry.getKey();
                        if (!CategoryWorker.isProductInCategory(delegator, productId, viewProductCategoryId)) {
                            products.remove(productId);
                            productQuantities.remove(productId);
                            productOccurances.remove(productId);
                        }
                    }
                }
            //}

            List<GenericValue> reorderProds = FastList.newInstance();
            reorderProds.addAll(products.values());

            /*
             //randomly remove products while there are more than 5
             while (reorderProds.size() > 5) {
             int toRemove = (int)(Math.random()*(double)(reorderProds.size()));
             reorderProds.remove(toRemove);
             }
             */

            // sort descending by new metric...
            BigDecimal occurancesModifier = BigDecimal.ONE;
            BigDecimal quantityModifier = BigDecimal.ONE;
            Map<String, Object> newMetric = FastMap.newInstance();
            for (Map.Entry<String, Integer> entry : productOccurances.entrySet()) {
                String prodId = entry.getKey();
                Integer quantity = entry.getValue();
                BigDecimal occs = productQuantities.get(prodId);
                //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, (String)prodId, cart.getProductStoreId())){
                    occs = occs.setScale(0, UtilNumber.getBigDecimalRoundingMode("order.rounding"));
                }
                else {
                    occs = occs.setScale(UtilNumber.getBigDecimalScale("order.decimals"), UtilNumber.getBigDecimalRoundingMode("order.rounding"));
                }
                productQuantities.put(prodId, occs);
                BigDecimal nqdbl = quantityModifier.multiply(new BigDecimal(quantity)).add(occs.multiply(occurancesModifier));

                newMetric.put(prodId, nqdbl);
            }
            reorderProds = productOrderByMap(reorderProds, newMetric, true);

            // remove extra products - only return 5
            while (reorderProds.size() > 5) {
                reorderProds.remove(reorderProds.size() - 1);
            }

            results.put("products", reorderProds);
            results.put("quantities", productQuantities);
        } catch (GenericEntityException e) {
            Debug.logWarning(e, module);
        }

        return results;
    }

    public static List<GenericValue> productOrderByMap(List<GenericValue> values, Map<String, Object> orderByMap, boolean descending) {
        if (values == null)  return null;
        if (values.size() == 0) return UtilMisc.toList(values);

        List<GenericValue> result = FastList.newInstance();
        result.addAll(values);

        Collections.sort(result, new ProductByMapComparator(orderByMap, descending));
        return result;
    }

    static class ProductByMapComparator implements Comparator<Object> {
        private Map<String, Object> orderByMap;
        private boolean descending;

        ProductByMapComparator(Map<String, Object> orderByMap, boolean descending) {
            this.orderByMap = orderByMap;
            this.descending = descending;
        }

        public int compare(java.lang.Object prod1, java.lang.Object prod2) {
            int result = compareAsc((GenericEntity) prod1, (GenericEntity) prod2);

            if (descending) {
                result = -result;
            }
            return result;
        }

        @SuppressWarnings("unchecked")
        private int compareAsc(GenericEntity prod1, GenericEntity prod2) {
            Object value = orderByMap.get(prod1.get("productId"));
            Object value2 = orderByMap.get(prod2.get("productId"));

            // null is defined as the smallest possible value
            if (value == null) return value2 == null ? 0 : -1;
            return ((Comparable<Object>) value).compareTo(value2);
        }

        @Override
        public boolean equals(java.lang.Object obj) {
            if ((obj != null) && (obj instanceof ProductByMapComparator)) {
                ProductByMapComparator that = (ProductByMapComparator) obj;

                return this.orderByMap.equals(that.orderByMap) && this.descending == that.descending;
            } else {
                return false;
            }
        }
    }
}
