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

import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;

import javolution.util.FastList;

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.base.util.UtilHttp;
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.EntityQuery;
import org.ofbiz.product.catalog.CatalogWorker;
import org.ofbiz.product.config.ProductConfigWrapper.ConfigItem;
import org.ofbiz.product.config.ProductConfigWrapper.ConfigOption;
import org.ofbiz.product.product.ProductWorker;
import org.ofbiz.product.store.ProductStoreWorker;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.webapp.website.WebSiteWorker;
import org.ofbiz.base.util.cache.Cache;
import org.ofbiz.base.util.cache.UtilCache;

/**
 * Product Config Worker class to reduce code in templates.
 */
public class ProductConfigWorker {

    public static final String module = ProductConfigWorker.class.getName();
    public static final String resource = "ProductUiLabels";
    public static final String SEPARATOR = "::";    // cache key separator

    private static final Cache<String, ProductConfigWrapper> productConfigCache = UtilCache.createUtilCache("product.config", true);     // use soft reference to free up memory if needed

    public static ProductConfigWrapper getProductConfigWrapper(String productId, String currencyUomId, HttpServletRequest request) {
        ProductConfigWrapper configWrapper = null;
        String catalogId = CatalogWorker.getCurrentCatalogId(request);
        String webSiteId = WebSiteWorker.getWebSiteId(request);
        String productStoreId = ProductStoreWorker.getProductStoreId(request);
        GenericValue autoUserLogin = (GenericValue)request.getSession().getAttribute("autoUserLogin");
        try {
            /* caching: there is one cache created, "product.config"  Each product's config wrapper is cached with a key of
             * productId::catalogId::webSiteId::currencyUomId, or whatever the SEPARATOR is defined above to be.
             */
            String cacheKey = productId + SEPARATOR + productStoreId + SEPARATOR + catalogId + SEPARATOR + webSiteId + SEPARATOR + currencyUomId;
            configWrapper = productConfigCache.get(cacheKey);
            if (configWrapper == null) {
                configWrapper = new ProductConfigWrapper((Delegator)request.getAttribute("delegator"),
                                                         (LocalDispatcher)request.getAttribute("dispatcher"),
                                                         productId, productStoreId, catalogId, webSiteId,
                                                         currencyUomId, UtilHttp.getLocale(request),
                                                         autoUserLogin);
                configWrapper = productConfigCache.putIfAbsentAndGet(cacheKey, new ProductConfigWrapper(configWrapper));
            } else {
                configWrapper = new ProductConfigWrapper(configWrapper);
            }
        } catch (ProductConfigWrapperException we) {
            configWrapper = null;
        } catch (Exception e) {
            Debug.logWarning(e.getMessage(), module);
        }
        return configWrapper;
    }

    public static void fillProductConfigWrapper(ProductConfigWrapper configWrapper, HttpServletRequest request) {
        int numOfQuestions = configWrapper.getQuestions().size();
        for (int k = 0; k < numOfQuestions; k++) {
            String[] opts = request.getParameterValues(Integer.toString(k));
            if (opts == null) {

                //  check for standard item comments
                ProductConfigWrapper.ConfigItem question = configWrapper.getQuestions().get(k);
                if (question.isStandard()) {
                    int i = 0;
                    while (i <= (question.getOptions().size() -1)) {
                        String comments = request.getParameter("comments_" + k + "_" + i);
                        if (UtilValidate.isNotEmpty(comments)) {
                            try {
                                configWrapper.setSelected(k, i, comments);
                            } catch (Exception e) {
                                Debug.logWarning(e.getMessage(), module);
                            }
                        }
                        i++;
                    }
                }
                continue;
            }
            for (String opt: opts) {
                int cnt = -1;
                try {
                    cnt = Integer.parseInt(opt);
                    String comments = null;
                    ProductConfigWrapper.ConfigItem question = configWrapper.getQuestions().get(k);
                    if (question.isSingleChoice()) {
                        comments = request.getParameter("comments_" + k + "_" + "0");
                    } else {
                        comments = request.getParameter("comments_" + k + "_" + cnt);
                    }

                    configWrapper.setSelected(k, cnt, comments);
                    ProductConfigWrapper.ConfigOption option = configWrapper.getItemOtion(k, cnt);

                    //  set selected variant products
                    if (UtilValidate.isNotEmpty(option) && (option.hasVirtualComponent())) {
                        List<GenericValue> components = option.getComponents();
                        int variantIndex = 0;
                        for (int i = 0; i < components.size(); i++) {
                            GenericValue component = components.get(i);
                            if (option.isVirtualComponent(component)) {
                                String productParamName = "add_product_id" + k + "_" + cnt + "_" + variantIndex;
                                String selectedProductId = request.getParameter(productParamName);
                                if (UtilValidate.isEmpty(selectedProductId)) {
                                    Debug.logWarning("ERROR: Request param [" + productParamName + "] not found!", module);
                                } else {

                                    //  handle also feature tree virtual variant methods
                                    if (ProductWorker.isVirtual((Delegator)request.getAttribute("delegator"), selectedProductId)) {
                                        if ("VV_FEATURETREE".equals(ProductWorker.getProductVirtualVariantMethod((Delegator)request.getAttribute("delegator"), selectedProductId))) {
                                            // get the selected features
                                            List<String> selectedFeatures = FastList.newInstance();
                                            Enumeration<String> paramNames = UtilGenerics.cast(request.getParameterNames());
                                            while (paramNames.hasMoreElements()) {
                                                String paramName = paramNames.nextElement();
                                                if (paramName.startsWith("FT" + k + "_" + cnt + "_" + variantIndex)) {
                                                    selectedFeatures.add(request.getParameterValues(paramName)[0]);
                                                }
                                            }

                                            // check if features are selected
                                            if (UtilValidate.isEmpty(selectedFeatures)) {
                                                Debug.logWarning("ERROR: No features selected for productId [" + selectedProductId+ "]", module);
                                            }

                                            String variantProductId = ProductWorker.getVariantFromFeatureTree(selectedProductId, selectedFeatures, (Delegator)request.getAttribute("delegator"));
                                            if (UtilValidate.isNotEmpty(variantProductId)) {
                                                selectedProductId = variantProductId;
                                            } else {
                                                Debug.logWarning("ERROR: Variant product not found!", module);
                                                request.setAttribute("_EVENT_MESSAGE_", UtilProperties.getMessage("OrderErrorUiLabels", "cart.addToCart.incompatibilityVariantFeature", UtilHttp.getLocale(request)));
                                           }
                                        }
                                    }
                                    configWrapper.setSelected(k, cnt, i, selectedProductId);
                                }
                                variantIndex ++;
                            }
                        }
                    }
                } catch (Exception e) {
                    Debug.logWarning(e.getMessage(), module);
                }
            }
        }
    }

    /**
     * First search persisted configurations and update configWrapper.configId if found.
     * Otherwise store ProductConfigWrapper to ProductConfigConfig entity and updates configWrapper.configId with new configId
     * This method persists only the selected options, price data is lost.
     * @param configWrapper the ProductConfigWrapper object
     * @param delegator the delegator
     */
    public static void storeProductConfigWrapper(ProductConfigWrapper configWrapper, Delegator delegator) {
        if (configWrapper == null || (!configWrapper.isCompleted()))  return;
        String configId = null;
        List<ConfigItem> questions = configWrapper.getQuestions();
        List<GenericValue> configsToCheck = FastList.newInstance();
        int selectedOptionSize = 0;
        for (ConfigItem ci: questions) {
            String configItemId = null;
            Long sequenceNum = null;
            List<ProductConfigWrapper.ConfigOption> selectedOptions = FastList.newInstance();
            List<ConfigOption> options = ci.getOptions();
            if (ci.isStandard()) {
                selectedOptions.addAll(options);
            } else {
                for (ConfigOption oneOption: options) {
                    if (oneOption.isSelected()) {
                        selectedOptions.add(oneOption);
                    }
                }
            }

            if (selectedOptions.size() > 0) {
                selectedOptionSize += selectedOptions.size();
                configItemId = ci.getConfigItemAssoc().getString("configItemId");
                sequenceNum = ci.getConfigItemAssoc().getLong("sequenceNum");
                try {
                    List<GenericValue> configs = EntityQuery.use(delegator).from("ProductConfigConfig").where("configItemId",configItemId,"sequenceNum", sequenceNum).queryList();
                    for (GenericValue productConfigConfig: configs) {
                        for (ConfigOption oneOption: selectedOptions) {
                            String configOptionId = oneOption.configOption.getString("configOptionId");
                            if (productConfigConfig.getString("configOptionId").equals(configOptionId)) {
                                String comments = oneOption.getComments() != null ? oneOption.getComments() : "";
                                if ((UtilValidate.isEmpty(comments) && UtilValidate.isEmpty(productConfigConfig.getString("description"))) || comments.equals(productConfigConfig.getString("description"))) {
                                    configsToCheck.add(productConfigConfig);
                                }
                            }
                        }
                    }

                } catch (GenericEntityException e) {
                    Debug.logError(e, module);
                }

            }
        }
        if (UtilValidate.isNotEmpty(configsToCheck)) {
            for (GenericValue productConfigConfig: configsToCheck) {
                String tempConfigId = productConfigConfig.getString("configId");
                try {
                    List<GenericValue> tempResult = EntityQuery.use(delegator).from("ProductConfigConfig").where("configId",tempConfigId).queryList();
                    if (tempResult.size() == selectedOptionSize && configsToCheck.containsAll(tempResult)) {
                        List<GenericValue> configOptionProductOptions = EntityQuery.use(delegator).from("ConfigOptionProductOption").where("configId",tempConfigId).queryList();
                        if (UtilValidate.isNotEmpty(configOptionProductOptions)) {

                            //  check for variant product equality
                            for (ConfigItem ci: questions) {
                                String configItemId = null;
                                Long sequenceNum = null;
                                List<ProductConfigWrapper.ConfigOption> selectedOptions = FastList.newInstance();
                                List<ConfigOption> options = ci.getOptions();
                                if (ci.isStandard()) {
                                    selectedOptions.addAll(options);
                                } else {
                                    for (ConfigOption oneOption: options) {
                                        if (oneOption.isSelected()) {
                                            selectedOptions.add(oneOption);
                                        }
                                    }
                                }

                                boolean match = true;
                                for (ProductConfigWrapper.ConfigOption anOption : selectedOptions) {
                                    if (match && anOption.hasVirtualComponent()) {
                                        List<GenericValue> components = anOption.getComponents();
                                        for (GenericValue aComponent : components) {
                                            if (anOption.isVirtualComponent(aComponent)) {
                                                Map<String, String> componentOptions = anOption.getComponentOptions();
                                                String optionProductId = aComponent.getString("productId");
                                                String optionProductOptionId = componentOptions.get(optionProductId);
                                                String configOptionId = anOption.configOption.getString("configOptionId");
                                                configItemId = ci.getConfigItemAssoc().getString("configItemId");
                                                sequenceNum = ci.getConfigItemAssoc().getLong("sequenceNum");

                                                GenericValue configOptionProductOption = delegator.makeValue("ConfigOptionProductOption");
                                                configOptionProductOption.set("configId", tempConfigId);
                                                configOptionProductOption.set("configItemId",configItemId);
                                                configOptionProductOption.set("sequenceNum", sequenceNum);
                                                configOptionProductOption.set("configOptionId", configOptionId);
                                                configOptionProductOption.set("productId", optionProductId);
                                                configOptionProductOption.set("productOptionId", optionProductOptionId);
                                                if (!configOptionProductOptions.remove(configOptionProductOption)) {
                                                    match = false;
                                                    break;
                                                }
                                            }
                                        }
                                    }
                                }

                                if (match && (UtilValidate.isEmpty(configOptionProductOptions))) {
                                    configWrapper.configId = tempConfigId;
                                    Debug.logInfo("Existing configuration found with configId:"+ tempConfigId,  module);
                                    return;
                                }
                            }

                        } else {
                            configWrapper.configId = tempConfigId;
                            Debug.logInfo("Existing configuration found with configId:"+ tempConfigId,  module);
                            return;
                        }
                    }
                } catch (GenericEntityException e) {
                    Debug.logError(e, module);
                }

            }
        }

        //Current configuration is not found in ProductConfigConfig entity. So lets store this one
        boolean nextId = true;
        for (ConfigItem ci: questions) {
            String configItemId = null;
            Long sequenceNum = null;
            List<ProductConfigWrapper.ConfigOption> selectedOptions = FastList.newInstance();
            List<ConfigOption> options = ci.getOptions();
           if (ci.isStandard()) {
                selectedOptions.addAll(options);
            } else {
                for (ConfigOption oneOption: options) {
                    if (oneOption.isSelected()) {
                        selectedOptions.add(oneOption);
                    }
                }
            }

            if (selectedOptions.size() > 0) {
                if (nextId) {
                    configId = delegator.getNextSeqId("ProductConfigConfig");
                    //get next configId only once and only if there are selectedOptions
                    nextId = false;
                }
                configItemId = ci.getConfigItemAssoc().getString("configItemId");
                sequenceNum = ci.getConfigItemAssoc().getLong("sequenceNum");
                for (ConfigOption oneOption: selectedOptions) {
                    List<GenericValue> toBeStored = FastList.newInstance();
                    String configOptionId = oneOption.configOption.getString("configOptionId");
                    String description = oneOption.getComments();
                    GenericValue productConfigConfig = delegator.makeValue("ProductConfigConfig");
                    productConfigConfig.put("configId", configId);
                    productConfigConfig.put("configItemId", configItemId);
                    productConfigConfig.put("sequenceNum", sequenceNum);
                    productConfigConfig.put("configOptionId", configOptionId);
                    productConfigConfig.put("description", description);
                    toBeStored.add(productConfigConfig);

                    if (oneOption.hasVirtualComponent()) {
                        List<GenericValue> components = oneOption.getComponents();
                        for (GenericValue component: components) {
                            if (oneOption.isVirtualComponent(component)) {
                                String componentOption = oneOption.componentOptions.get(component.getString("productId"));
                                GenericValue configOptionProductOption = delegator.makeValue("ConfigOptionProductOption");
                                configOptionProductOption.put("configId", configId);
                                configOptionProductOption.put("configItemId", configItemId);
                                configOptionProductOption.put("sequenceNum", sequenceNum);
                                configOptionProductOption.put("configOptionId", configOptionId);
                                configOptionProductOption.put("productId", component.getString("productId"));
                                configOptionProductOption.put("productOptionId", componentOption);
                                toBeStored.add(configOptionProductOption);
                            }
                        }
                    }
                    try {
                        delegator.storeAll(toBeStored);
                    } catch (GenericEntityException e) {
                        configId = null;
                        Debug.logWarning(e.getMessage(), module);
                    }
                }
            }
        }

        //save  configId to configWrapper, so we can use it in shopping cart operations
        configWrapper.configId = configId;
        Debug.logInfo("New configId created:"+ configId,  module);
        return;
    }

    /**
     * Creates a new ProductConfigWrapper for productId and configures it according to ProductConfigConfig entity with configId
     * ProductConfigConfig entity stores only the selected options, and the product price is calculated from input params
     * @param delegator
     * @param dispatcher
     * @param configId configuration Id
     * @param productId AGGRAGATED productId
     * @param productStoreId needed for price calculations
     * @param catalogId needed for price calculations
     * @param webSiteId needed for price calculations
     * @param currencyUomId needed for price calculations
     * @param locale
     * @param autoUserLogin
     * @return ProductConfigWrapper
     */
    public static ProductConfigWrapper loadProductConfigWrapper(Delegator delegator, LocalDispatcher dispatcher, String configId, String productId, String productStoreId, String catalogId, String webSiteId, String currencyUomId, Locale locale, GenericValue autoUserLogin) {
        ProductConfigWrapper configWrapper = null;
        try {
             configWrapper = new ProductConfigWrapper(delegator, dispatcher, productId, productStoreId, catalogId, webSiteId, currencyUomId, locale, autoUserLogin);
            if (configWrapper != null && UtilValidate.isNotEmpty(configId)) {
                configWrapper.loadConfig(delegator, configId);
            }
        } catch (Exception e) {
            Debug.logWarning(e.getMessage(), module);
            configWrapper = null;
        }
        return configWrapper;
    }

}

