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

import java.math.BigDecimal;
import java.math.MathContext;
import java.util.List;
import java.util.Map;

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

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilProperties;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.service.DispatchContext;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.ModelService;

/**
 * ShipmentWorker - Worker methods for Shipment and related entities
 */
public class ShipmentWorker {

    public static final String module = ShipmentWorker.class.getName();
    public static final MathContext generalRounding = new MathContext(10);
    /*
     * Returns the value of a given ShipmentPackageContent record.  Calculated by working out the total value (from the OrderItems) of all ItemIssuances
     * for the ShipmentItem then dividing that by the total quantity issued for the same to get an average item value then multiplying that by the package
     * content quantity.
     * Note: No rounding of the calculation is performed so you will need to round it to the accuracy that you require
     */
    public static BigDecimal getShipmentPackageContentValue(GenericValue shipmentPackageContent) {
        BigDecimal quantity = shipmentPackageContent.getBigDecimal("quantity");

        BigDecimal value = new BigDecimal("0");

        // lookup the issuance to find the order
        List<GenericValue> issuances = null;
        try {
            GenericValue shipmentItem = shipmentPackageContent.getRelatedOne("ShipmentItem", false);
            issuances = shipmentItem.getRelated("ItemIssuance", null, null, false);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }

        BigDecimal totalIssued = BigDecimal.ZERO;
        BigDecimal totalValue = BigDecimal.ZERO;
        if (UtilValidate.isNotEmpty(issuances)) {
            for (GenericValue issuance : issuances) {
                // we only need one
                BigDecimal issuanceQuantity = issuance.getBigDecimal("quantity");
                BigDecimal issuanceCancelQuantity = issuance.getBigDecimal("cancelQuantity");
                if (issuanceCancelQuantity != null) {
                    issuanceQuantity = issuanceQuantity.subtract(issuanceCancelQuantity);
                }
                // get the order item
                GenericValue orderItem = null;
                try {
                    orderItem = issuance.getRelatedOne("OrderItem", false);
                } catch (GenericEntityException e) {
                    Debug.logError(e, module);
                }

                if (orderItem != null) {
                    // get the value per unit - (base price * amount)
                    BigDecimal selectedAmount = orderItem.getBigDecimal("selectedAmount");
                    if (selectedAmount == null || selectedAmount.compareTo(BigDecimal.ZERO) <= 0) {
                        selectedAmount = BigDecimal.ONE;
                    }

                    BigDecimal unitPrice = orderItem.getBigDecimal("unitPrice");
                    BigDecimal itemValue = unitPrice.multiply(selectedAmount);

                    // total value for package (per unit * quantity)
                    totalIssued = totalIssued.add(issuanceQuantity);
                    totalValue = totalValue.add(itemValue.multiply(issuanceQuantity));
                }
            }
        }
        // take the average value of the issuances and multiply it by the shipment package content quantity
        value = totalValue.divide(totalIssued, 10, BigDecimal.ROUND_HALF_EVEN).multiply(quantity);
        return value;
    }

    public static List<Map<String, BigDecimal>> getPackageSplit(DispatchContext dctx, List<Map<String, Object>> shippableItemInfo, BigDecimal maxWeight) {
        // create the package list w/ the first package
        List<Map<String, BigDecimal>> packages = FastList.newInstance();

        if (UtilValidate.isNotEmpty(shippableItemInfo)) {
            for (Map<String, Object> itemInfo: shippableItemInfo) {
                long pieces = ((Long) itemInfo.get("piecesIncluded")).longValue();
                BigDecimal totalQuantity = (BigDecimal) itemInfo.get("quantity");
                BigDecimal totalWeight = (BigDecimal) itemInfo.get("weight");
                String productId = (String) itemInfo.get("productId");

                // sanity check
                if (pieces < 1) {
                    pieces = 1; // can NEVER be less than one
                }
                BigDecimal weight = totalWeight.divide(BigDecimal.valueOf(pieces), generalRounding);
                for (int z = 1; z <= totalQuantity.intValue(); z++) {
                    BigDecimal partialQty = pieces > 1 ? BigDecimal.ONE.divide(BigDecimal.valueOf(pieces), generalRounding) : BigDecimal.ONE;
                    for (long x = 0; x < pieces; x++) {
                        if (weight.compareTo(maxWeight) >= 0) {
                            Map<String, BigDecimal> newPackage = FastMap.newInstance();
                            newPackage.put(productId, partialQty);
                            packages.add(newPackage);
                        } else if (totalWeight.compareTo(BigDecimal.ZERO) > 0) {
                            // create the first package
                            if (packages.size() == 0) {
                                packages.add(FastMap.<String, BigDecimal>newInstance());
                            }

                            // package loop
                            boolean addedToPackage = false;
                            for (Map<String, BigDecimal> packageMap: packages) {
                                if (!addedToPackage) {
                                    BigDecimal packageWeight = calcPackageWeight(dctx, packageMap, shippableItemInfo, weight);
                                    if (packageWeight.compareTo(maxWeight) <= 0) {
                                        BigDecimal qty = packageMap.get(productId);
                                        qty = UtilValidate.isEmpty(qty) ? BigDecimal.ZERO : qty;
                                        packageMap.put(productId, qty.add(partialQty));
                                        addedToPackage = true;
                                    }
                                }
                            }
                            if (!addedToPackage) {
                                Map<String, BigDecimal> packageMap = FastMap.newInstance();
                                packageMap.put(productId, partialQty);
                                packages.add(packageMap);
                            }
                        }
                    }
                }
            }
        }
        return packages;
    }

    public static BigDecimal calcPackageWeight(DispatchContext dctx, Map<String, BigDecimal> packageMap, List<Map<String, Object>> shippableItemInfo, BigDecimal additionalWeight) {

        LocalDispatcher dispatcher = dctx.getDispatcher();
        BigDecimal totalWeight = BigDecimal.ZERO;
        String defaultWeightUomId = UtilProperties.getPropertyValue("shipment.properties", "shipment.default.weight.uom");

        for (Map.Entry<String, BigDecimal> entry: packageMap.entrySet()) {
            String productId = entry.getKey();
            Map<String, Object> productInfo = getProductItemInfo(shippableItemInfo, productId);
            BigDecimal productWeight = (BigDecimal) productInfo.get("weight");
            BigDecimal quantity = packageMap.get(productId);

            String weightUomId = (String) productInfo.get("weightUomId");

            Debug.logInfo("Product Id : " + productId.toString() + " Product Weight : " + String.valueOf(productWeight) + " Product UomId : " + weightUomId + " assuming " + defaultWeightUomId + " if null. Quantity : " + String.valueOf(quantity), module);

            if (UtilValidate.isEmpty(weightUomId)) {
                weightUomId = defaultWeightUomId;
            }
            if (!"WT_lb".equals(weightUomId)) {
                // attempt a conversion to pounds
                Map<String, Object> result = FastMap.newInstance();
                try {
                    result = dispatcher.runSync("convertUom", UtilMisc.<String, Object>toMap("uomId", weightUomId, "uomIdTo", "WT_lb", "originalValue", productWeight));
                } catch (GenericServiceException ex) {
                    Debug.logError(ex, module);
                }
                if (result.get(ModelService.RESPONSE_MESSAGE).equals(ModelService.RESPOND_SUCCESS) && UtilValidate.isNotEmpty(result.get("convertedValue"))) {
                    productWeight = (BigDecimal) result.get("convertedValue");
                } else {
                    Debug.logError("Unsupported weightUom [" + weightUomId + "] for calcPackageWeight running productId " + productId + ", could not find a conversion factor to WT_lb",module);
                }
            }

            totalWeight = totalWeight.add(productWeight.multiply(quantity));
        }
        Debug.logInfo("Package Weight : " + String.valueOf(totalWeight) + " lbs.", module);
        return totalWeight.add(additionalWeight);
    }

    public static Map<String, Object> getProductItemInfo(List<Map<String, Object>> shippableItemInfo, String productId) {
        if (UtilValidate.isNotEmpty(shippableItemInfo)) {
            for (Map<String, Object> itemInfoMap: shippableItemInfo) {
                String compareProductId = (String) itemInfoMap.get("productId");
                if (productId.equals(compareProductId)) {
                    return itemInfoMap;
                }
            }
        }
        return null;
    }
}
