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

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

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

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.base.util.UtilMisc;
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.service.DispatchContext;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.ModelService;
import org.ofbiz.service.ServiceUtil;


/**
 * Services for product features
 */

public class ProductFeatureServices {

    public static final String module = ProductFeatureServices.class.getName();
    public static final String resource = "ProductUiLabels";

    /*
     * Parameters: productFeatureCategoryId, productFeatureGroupId, productId, productFeatureApplTypeId
     * Result: productFeaturesByType, a Map of all product features from productFeatureCategoryId, group by productFeatureType -> List of productFeatures
     * If the parameter were productFeatureCategoryId, the results are from ProductFeatures.  If productFeatureCategoryId were null and there were a productFeatureGroupId,
     * the results are from ProductFeatureGroupAndAppl.  Otherwise, if there is a productId, the results are from ProductFeatureAndAppl.
     * The optional productFeatureApplTypeId causes results to be filtered by this parameter--only used in conjunction with productId.
     */
    public static Map<String, Object> getProductFeaturesByType(DispatchContext dctx, Map<String, ? extends Object> context) {
        Map<String, Object> results = FastMap.newInstance();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");

        /* because we might need to search either for product features or for product features of a product, the search code has to be generic.
         * we will determine which entity and field to search on based on what the user has supplied us with.
         */
        String valueToSearch = (String) context.get("productFeatureCategoryId");
        String productFeatureApplTypeId = (String) context.get("productFeatureApplTypeId");

        String entityToSearch = "ProductFeature";
        String fieldToSearch = "productFeatureCategoryId";
        List<String> orderBy = UtilMisc.toList("productFeatureTypeId", "description");

        if (valueToSearch == null && context.get("productFeatureGroupId") != null) {
            entityToSearch = "ProductFeatureGroupAndAppl";
            fieldToSearch = "productFeatureGroupId";
            valueToSearch = (String) context.get("productFeatureGroupId");
            // use same orderBy as with a productFeatureCategoryId search
        } else if (valueToSearch == null && context.get("productId") != null) {
            entityToSearch = "ProductFeatureAndAppl";
            fieldToSearch = "productId";
            valueToSearch = (String) context.get("productId");
            orderBy = UtilMisc.toList("sequenceNum", "productFeatureApplTypeId", "productFeatureTypeId", "description");
        }

        if (valueToSearch == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductFeatureByType", locale));
        }

        try {
            // get all product features in this feature category
            List<GenericValue> allFeatures = delegator.findByAnd(entityToSearch, UtilMisc.toMap(fieldToSearch, valueToSearch), orderBy, false);

            if (entityToSearch.equals("ProductFeatureAndAppl") && productFeatureApplTypeId != null)
                allFeatures = EntityUtil.filterByAnd(allFeatures, UtilMisc.toMap("productFeatureApplTypeId", productFeatureApplTypeId));

            List<String> featureTypes = FastList.newInstance();
            Map<String, List<GenericValue>> featuresByType = new LinkedHashMap<String, List<GenericValue>>();
            for (GenericValue feature: allFeatures) {
                String featureType = feature.getString("productFeatureTypeId");
                if (!featureTypes.contains(featureType)) {
                    featureTypes.add(featureType);
                }
                List<GenericValue> features = featuresByType.get(featureType);
                if (features == null) {
                    features = FastList.newInstance();
                    featuresByType.put(featureType, features);
                }
                features.add(feature);
            }

            results = ServiceUtil.returnSuccess();
            results.put("productFeatureTypes", featureTypes);
            results.put("productFeaturesByType", featuresByType);
        } catch (GenericEntityException ex) {
            Debug.logError(ex, ex.getMessage(), module);
            return ServiceUtil.returnError(ex.getMessage());
        }
        return results;
    }

    /*
     * Parameter: productId, productFeatureAppls (a List of ProductFeatureAndAppl entities of features applied to productId)
     * Result: variantProductIds: a List of productIds of variants with those features
     */
    public static Map<String, Object> getAllExistingVariants(DispatchContext dctx, Map<String, ? extends Object> context) {
        Map<String, Object> results = FastMap.newInstance();
        Delegator delegator = dctx.getDelegator();

        String productId = (String) context.get("productId");
        List<String> curProductFeatureAndAppls = UtilGenerics.checkList(context.get("productFeatureAppls"));
        List<String> existingVariantProductIds = FastList.newInstance();

        try {
            /*
             * get a list of all products which are associated with the current one as PRODUCT_VARIANT and for each one,
             * see if it has every single feature in the list of productFeatureAppls as a STANDARD_FEATURE.  If so, then
             * it qualifies and add it to the list of existingVariantProductIds.
             */
            List<GenericValue> productAssocs = EntityUtil.filterByDate(delegator.findByAnd("ProductAssoc", UtilMisc.toMap("productId", productId, "productAssocTypeId", "PRODUCT_VARIANT"), null, false));
            for (GenericValue productAssoc: productAssocs) {

                //for each associated product, if it has all standard features, display it's productId
                boolean hasAllFeatures = true;
                for (String productFeatureAndAppl: curProductFeatureAndAppls) {
                    Map<String, String> findByMap = UtilMisc.toMap("productId", productAssoc.getString("productIdTo"),
                            "productFeatureId", productFeatureAndAppl,
                            "productFeatureApplTypeId", "STANDARD_FEATURE");

                    //Debug.logInfo("Using findByMap: " + findByMap);

                    List<GenericValue> standardProductFeatureAndAppls = EntityUtil.filterByDate(delegator.findByAnd("ProductFeatureAppl", findByMap, null, false));
                    if (UtilValidate.isEmpty(standardProductFeatureAndAppls)) {
                        // Debug.logInfo("Does NOT have this standard feature");
                        hasAllFeatures = false;
                        break;
                    } else {
                        // Debug.logInfo("DOES have this standard feature");
                    }
                }

                if (hasAllFeatures) {
                    // add to list of existing variants: productId=productAssoc.productIdTo
                    existingVariantProductIds.add(productAssoc.getString("productIdTo"));
                }
            }
            results = ServiceUtil.returnSuccess();
            results.put("variantProductIds", existingVariantProductIds);
        } catch (GenericEntityException ex) {
            Debug.logError(ex, ex.getMessage(), module);
            return ServiceUtil.returnError(ex.getMessage());
        }
    return results;
    }

    /*
     * Parameter: productId (of the parent product which has SELECTABLE features)
     * Result: featureCombinations, a List of Maps containing, for each possible variant of the productid:
     * {defaultVariantProductId: id of this variant; curProductFeatureAndAppls: features applied to this variant; existingVariantProductIds: List of productIds which are already variants with these features }
     */
    public static Map<String, Object> getVariantCombinations(DispatchContext dctx, Map<String, ? extends Object> context) {
        Map<String, Object> results = FastMap.newInstance();
        LocalDispatcher dispatcher = dctx.getDispatcher();

        String productId = (String) context.get("productId");

        try {
            Map<String, Object> featuresResults = dispatcher.runSync("getProductFeaturesByType", UtilMisc.toMap("productId", productId));
            Map<String, List<GenericValue>> features;

            if (featuresResults.get(ModelService.RESPONSE_MESSAGE).equals(ModelService.RESPOND_SUCCESS)) {
                features = UtilGenerics.checkMap(featuresResults.get("productFeaturesByType"));
            } else {
                return ServiceUtil.returnError((String) featuresResults.get(ModelService.ERROR_MESSAGE_LIST));
            }

            // need to keep 2 lists, oldCombinations and newCombinations, and keep swapping them after each looping.  Otherwise, you'll get a
            // concurrent modification exception
            List<Map<String, Object>> oldCombinations = FastList.newInstance();

            // loop through each feature type
            for (Map.Entry<String, List<GenericValue>> entry: features.entrySet()) {
                List<GenericValue> currentFeatures = entry.getValue();

                List<Map<String, Object>> newCombinations = FastList.newInstance();
                List<Map<String, Object>> combinations;

                // start with either existing combinations or from scratch
                if (oldCombinations.size() > 0) {
                    combinations = oldCombinations;
                } else {
                    combinations = FastList.newInstance();
                }

                // in both cases, use each feature of current feature type's idCode and
                // product feature and add it to the id code and product feature applications
                // of the next variant.  just a matter of whether we're starting with an
                // existing list of features and id code or from scratch.
                if (combinations.size()==0) {
                    for (GenericValue currentFeature: currentFeatures) {
                        if (currentFeature.getString("productFeatureApplTypeId").equals("SELECTABLE_FEATURE")) {
                            Map<String, Object> newCombination = FastMap.newInstance();
                            List<GenericValue> newFeatures = FastList.newInstance();
                            List<String> newFeatureIds = FastList.newInstance();
                            if (currentFeature.getString("idCode") != null) {
                                newCombination.put("defaultVariantProductId", productId + currentFeature.getString("idCode"));
                            } else {
                                newCombination.put("defaultVariantProductId", productId);
                            }
                            newFeatures.add(currentFeature);
                            newFeatureIds.add(currentFeature.getString("productFeatureId"));
                            newCombination.put("curProductFeatureAndAppls", newFeatures);
                            newCombination.put("curProductFeatureIds", newFeatureIds);
                            newCombinations.add(newCombination);
                        }
                    }
                } else {
                    for (Map<String, Object> combination: combinations) {
                        for (GenericValue currentFeature: currentFeatures) {
                            if (currentFeature.getString("productFeatureApplTypeId").equals("SELECTABLE_FEATURE")) {
                                Map<String, Object> newCombination = FastMap.newInstance();
                                // .clone() is important, or you'll keep adding to the same List for all the variants
                                // have to cast twice: once from get() and once from clone()
                                List<GenericValue> newFeatures = UtilMisc.makeListWritable(UtilGenerics.<GenericValue>checkList(combination.get("curProductFeatureAndAppls")));
                                List<String> newFeatureIds = UtilMisc.makeListWritable(UtilGenerics.<String>checkList(combination.get("curProductFeatureIds")));
                                if (currentFeature.getString("idCode") != null) {
                                    newCombination.put("defaultVariantProductId", combination.get("defaultVariantProductId") + currentFeature.getString("idCode"));
                                } else {
                                    newCombination.put("defaultVariantProductId", combination.get("defaultVariantProductId"));
                                }
                                newFeatures.add(currentFeature);
                                newFeatureIds.add(currentFeature.getString("productFeatureId"));
                                newCombination.put("curProductFeatureAndAppls", newFeatures);
                                newCombination.put("curProductFeatureIds", newFeatureIds);
                                newCombinations.add(newCombination);
                            }
                        }
                    }
                }
                if (newCombinations.size() >= oldCombinations.size()) {
                    oldCombinations = newCombinations; // save the newly expanded list as oldCombinations
                }
            }

            int defaultCodeCounter = 1;
            Set<String> defaultVariantProductIds = FastSet.newInstance(); // this map will contain the codes already used (as keys)
            defaultVariantProductIds.add(productId);

            // now figure out which of these combinations already have productIds associated with them
            for (Map<String, Object> combination: oldCombinations) {
                // Verify if the default code is already used, if so add a numeric suffix
                if (defaultVariantProductIds.contains(combination.get("defaultVariantProductId"))) {
                    combination.put("defaultVariantProductId", combination.get("defaultVariantProductId") + "-" + (defaultCodeCounter < 10? "0" + defaultCodeCounter: "" + defaultCodeCounter));
                    defaultCodeCounter++;
                }
                defaultVariantProductIds.add((String) combination.get("defaultVariantProductId"));
                results = dispatcher.runSync("getAllExistingVariants", UtilMisc.toMap("productId", productId,
                                             "productFeatureAppls", combination.get("curProductFeatureIds")));
                combination.put("existingVariantProductIds", results.get("variantProductIds"));
            }
            results = ServiceUtil.returnSuccess();
            results.put("featureCombinations", oldCombinations);
        } catch (GenericServiceException ex) {
            Debug.logError(ex, ex.getMessage(), module);
            return ServiceUtil.returnError(ex.getMessage());
        }

        return results;
    }

    /*
     * Parameters: productCategoryId (String) and productFeatures (a List of ProductFeature GenericValues)
     * Result: products (a List of Product GenericValues)
     */
    public static Map<String, Object> getCategoryVariantProducts(DispatchContext dctx, Map<String, ? extends Object> context) {
        Map<String, Object> results = FastMap.newInstance();
        LocalDispatcher dispatcher = dctx.getDispatcher();

        List<GenericValue> productFeatures = UtilGenerics.checkList(context.get("productFeatures"));
        String productCategoryId = (String) context.get("productCategoryId");
        Locale locale = (Locale) context.get("locale");

        // get all the product members of the product category
        Map<String, Object> result;
        try {
            result = dispatcher.runSync("getProductCategoryMembers", UtilMisc.toMap("categoryId", productCategoryId));
        } catch (GenericServiceException ex) {
            Debug.logError("Cannot get category memebers for " + productCategoryId + " due to error: " + ex.getMessage(), module);
            return ServiceUtil.returnError(ex.getMessage());
        }

        List<GenericValue> memberProducts = UtilGenerics.checkList(result.get("categoryMembers"));
        if ((memberProducts != null) && (memberProducts.size() > 0)) {
            // construct a Map of productFeatureTypeId -> productFeatureId from the productFeatures List
            Map<String, String> featuresByType = FastMap.newInstance();
            for (GenericValue nextFeature: productFeatures) {
                featuresByType.put(nextFeature.getString("productFeatureTypeId"), nextFeature.getString("productFeatureId"));
            }

            List<GenericValue> products = FastList.newInstance();  // final list of variant products
            for (GenericValue memberProduct: memberProducts) {
                // find variants for each member product of the category

                try {
                    result = dispatcher.runSync("getProductVariant", UtilMisc.toMap("productId", memberProduct.getString("productId"), "selectedFeatures", featuresByType));
                } catch (GenericServiceException ex) {
                    Debug.logError("Cannot get product variants for " + memberProduct.getString("productId") + " due to error: " + ex.getMessage(), module);
                    return ServiceUtil.returnError(ex.getMessage());
                }

                List<GenericValue> variantProducts = UtilGenerics.checkList(result.get("products"));
                if ((variantProducts != null) && (variantProducts.size() > 0)) {
                    products.addAll(variantProducts);
                } else {
                    Debug.logWarning("Product " + memberProduct.getString("productId") + " did not have any variants for the given features", module);
                }
            }

            if (products.size() == 0) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductCategoryNoVariants", locale));
            } else {
                results = ServiceUtil.returnSuccess();
                results.put("products", products);
            }

        } else {
            Debug.logWarning("No products found in " + productCategoryId, module);
        }

        return results;
    }
}
