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

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javolution.util.FastMap;

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilDateTime;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilProperties;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.common.uom.UomWorker;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.condition.EntityCondition;
import org.ofbiz.entity.condition.EntityOperator;
import org.ofbiz.entity.util.EntityQuery;
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;

import com.ibm.icu.util.Calendar;

/**
 * Subscription Services
 */
public class SubscriptionServices {

    public static final String module = SubscriptionServices.class.getName();
    public static final String resource = "ProductUiLabels";
    public static final String resourceOrderError = "OrderErrorUiLabels";
    
    public static Map<String, Object> processExtendSubscription(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Timestamp nowTimestamp = UtilDateTime.nowTimestamp();

        String partyId = (String) context.get("partyId");
        String subscriptionResourceId = (String) context.get("subscriptionResourceId");
        String inventoryItemId = (String) context.get("inventoryItemId");
        String roleTypeId = (String) context.get("useRoleTypeId");
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Integer useTime = (Integer) context.get("useTime");
        String useTimeUomId = (String) context.get("useTimeUomId");
        String alwaysCreateNewRecordStr = (String) context.get("alwaysCreateNewRecord");
        Locale locale = (Locale) context.get("locale");
        boolean alwaysCreateNewRecord = !"N".equals(alwaysCreateNewRecordStr);

        GenericValue lastSubscription = null;
        try {
            Map<String, String> subscriptionFindMap = UtilMisc.toMap("partyId", partyId, "subscriptionResourceId", subscriptionResourceId);
            // if this subscription is attached to something the customer owns, filter by that too
            if (UtilValidate.isNotEmpty(inventoryItemId)) subscriptionFindMap.put("inventoryItemId", inventoryItemId);
            List<GenericValue> subscriptionList = EntityQuery.use(delegator).from("Subscription").where(subscriptionFindMap).queryList();
            // DEJ20070718 DON'T filter by date, we want to consider all subscriptions: List listFiltered = EntityUtil.filterByDate(subscriptionList, true);
            List<GenericValue> listOrdered = EntityUtil.orderBy(subscriptionList, UtilMisc.toList("-fromDate"));
            if (listOrdered.size() > 0) {
                lastSubscription = listOrdered.get(0);
            }
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.toString());
        }

        GenericValue newSubscription = null;
        if (lastSubscription == null || alwaysCreateNewRecord) {
            newSubscription = delegator.makeValue("Subscription");
            newSubscription.set("subscriptionResourceId", subscriptionResourceId);
            newSubscription.set("partyId", partyId);
            newSubscription.set("roleTypeId", roleTypeId);
            newSubscription.set("productId", context.get("productId"));
            newSubscription.set("orderId", context.get("orderId"));
            newSubscription.set("orderItemSeqId", context.get("orderItemSeqId"));
            newSubscription.set("automaticExtend", context.get("automaticExtend"));
            newSubscription.set("canclAutmExtTimeUomId", context.get("canclAutmExtTimeUomId"));
            newSubscription.set("canclAutmExtTime", context.get("canclAutmExtTime"));
        } else {
            newSubscription = lastSubscription;
        }
        newSubscription.set("inventoryItemId", inventoryItemId);

        Timestamp thruDate = lastSubscription != null ? (Timestamp) lastSubscription.get("thruDate") : null;

        // set the fromDate, one way or another
        if (thruDate == null) {
            // no thruDate? start with NOW
            thruDate = nowTimestamp;
            newSubscription.set("fromDate", nowTimestamp);
        } else {
            // there is a thru date... if it is in the past, bring it up to NOW before adding on the time period
            // don't want to penalize for skipping time, in other words if they had a subscription last year for a
            // month and buy another month, we want that second month to start now and not last year
            if (thruDate.before(nowTimestamp)) {
                thruDate = nowTimestamp;
            }
            newSubscription.set("fromDate", thruDate);
        }

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(thruDate);
        int[] times = UomWorker.uomTimeToCalTime(useTimeUomId);
        if (times != null) {
            calendar.add(times[0], (useTime.intValue() * times[1]));
        } else {
            Debug.logWarning("Don't know anything about useTimeUomId [" + useTimeUomId + "], defaulting to month", module);
            calendar.add(Calendar.MONTH, useTime);
        }

        thruDate = new Timestamp(calendar.getTimeInMillis());
        newSubscription.set("thruDate", thruDate);

        Map<String, Object> result = ServiceUtil.returnSuccess();
        try {
            if (lastSubscription != null && !alwaysCreateNewRecord) {
                Map<String, Object> updateSubscriptionMap = dctx.getModelService("updateSubscription").makeValid(newSubscription, ModelService.IN_PARAM);
                updateSubscriptionMap.put("userLogin", EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne());

                Map<String, Object> updateSubscriptionResult = dispatcher.runSync("updateSubscription", updateSubscriptionMap);
                result.put("subscriptionId", updateSubscriptionMap.get("subscriptionId"));
                if (ServiceUtil.isError(updateSubscriptionResult)) {
                    return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                            "ProductSubscriptionUpdateError", 
                            UtilMisc.toMap("subscriptionId", updateSubscriptionMap.get("subscriptionId")), locale),
                            null, null, updateSubscriptionResult);
                }
            } else {
                Map<String, Object> ensurePartyRoleMap = FastMap.newInstance();
                if (UtilValidate.isNotEmpty(roleTypeId)) {
                    ensurePartyRoleMap.put("partyId", partyId);
                    ensurePartyRoleMap.put("roleTypeId", roleTypeId);
                    ensurePartyRoleMap.put("userLogin", userLogin);
                    Map<String, Object> ensurePartyRoleResult = dispatcher.runSync("ensurePartyRole", ensurePartyRoleMap);
                    if (ServiceUtil.isError(ensurePartyRoleResult)) {
                        return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                                "ProductSubscriptionPartyRoleCreationError", 
                                UtilMisc.toMap("subscriptionResourceId", subscriptionResourceId), locale),
                                null, null, ensurePartyRoleResult);
                    }
                }
                Map<String, Object> createSubscriptionMap = dctx.getModelService("createSubscription").makeValid(newSubscription, ModelService.IN_PARAM);
                createSubscriptionMap.put("userLogin", EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne());

                Map<String, Object> createSubscriptionResult = dispatcher.runSync("createSubscription", createSubscriptionMap);
                if (ServiceUtil.isError(createSubscriptionResult)) {
                    return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                            "ProductSubscriptionCreateError", 
                            UtilMisc.toMap("subscriptionResourceId", subscriptionResourceId), locale),
                            null, null, createSubscriptionResult);
                }
                result.put("subscriptionId", createSubscriptionResult.get("subscriptionId"));
            }
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.toString());
        } catch (GenericServiceException e) {
            return ServiceUtil.returnError(e.toString());
        }
        return result;
    }

    public static Map<String, Object> processExtendSubscriptionByProduct(DispatchContext dctx, Map<String, ? extends Object> context) throws GenericServiceException{
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        String productId = (String) context.get("productId");
        Integer qty = (Integer) context.get("quantity");
        Locale locale = (Locale) context.get("locale");
        if (qty == null) {
            qty = Integer.valueOf(1);
        }

        Timestamp orderCreatedDate = (Timestamp) context.get("orderCreatedDate");
        if (orderCreatedDate == null) {
            orderCreatedDate = UtilDateTime.nowTimestamp();
        }
        try {
            List<GenericValue> productSubscriptionResourceList = EntityQuery.use(delegator).from("ProductSubscriptionResource")
                    .where("productId", productId)
                    .cache(true)
                    .filterByDate(orderCreatedDate, "fromDate", "thruDate", "purchaseFromDate", "purchaseThruDate")
                    .queryList();

            if (productSubscriptionResourceList.size() == 0) {
                Debug.logError("No ProductSubscriptionResource found for productId: " + productId, module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                        "ProductSubscriptionResourceNotFound", 
                        UtilMisc.toMap("productId", productId), locale));
            }

            for (GenericValue productSubscriptionResource: productSubscriptionResourceList) {
                Long useTime = productSubscriptionResource.getLong("useTime");
                Integer newUseTime = Integer.valueOf(0);
                if (useTime != null) {
                    newUseTime = Integer.valueOf(useTime.intValue() * qty.intValue());
                }
                Map<String, Object> subContext = UtilMisc.makeMapWritable(context);
                subContext.put("useTime", newUseTime);
                subContext.put("useTimeUomId", productSubscriptionResource.get("useTimeUomId"));
                subContext.put("useRoleTypeId", productSubscriptionResource.get("useRoleTypeId"));
                subContext.put("subscriptionResourceId", productSubscriptionResource.get("subscriptionResourceId"));
                subContext.put("automaticExtend", productSubscriptionResource.get("automaticExtend"));
                subContext.put("canclAutmExtTime", productSubscriptionResource.get("canclAutmExtTime"));
                subContext.put("canclAutmExtTimeUomId", productSubscriptionResource.get("canclAutmExtTimeUomId"));
                subContext.put("gracePeriodOnExpiry", productSubscriptionResource.get("gracePeriodOnExpiry"));
                subContext.put("gracePeriodOnExpiryUomId", productSubscriptionResource.get("gracePeriodOnExpiryUomId"));

                Map<String, Object> ctx = dctx.getModelService("processExtendSubscription").makeValid(subContext, ModelService.IN_PARAM);
                Map<String, Object> processExtendSubscriptionResult = dispatcher.runSync("processExtendSubscription", ctx);
                if (ServiceUtil.isError(processExtendSubscriptionResult)) {
                    return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                            "ProductSubscriptionByProductError", 
                            UtilMisc.toMap("productId", productId), locale),
                            null, null, processExtendSubscriptionResult);
                }
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, e.toString(), module);
            return ServiceUtil.returnError(e.toString());
        }

        return ServiceUtil.returnSuccess();
    }

    public static Map<String, Object> processExtendSubscriptionByOrder(DispatchContext dctx, Map<String, ? extends Object> context) throws GenericServiceException{
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Map<String, Object> subContext = UtilMisc.makeMapWritable(context);
        String orderId = (String) context.get("orderId");
        Locale locale = (Locale) context.get("locale");

        Debug.logInfo("In processExtendSubscriptionByOrder service with orderId: " + orderId, module);

        GenericValue orderHeader = null;
        try {
            List<GenericValue> orderRoleList = EntityQuery.use(delegator).from("OrderRole").where("orderId", orderId, "roleTypeId", "END_USER_CUSTOMER").queryList();
            if (orderRoleList.size() > 0) {
                GenericValue orderRole = orderRoleList.get(0);
                String partyId = (String) orderRole.get("partyId");
                subContext.put("partyId", partyId);
            } else {
                return ServiceUtil.returnFailure(UtilProperties.getMessage(resourceOrderError, 
                        "OrderErrorCannotGetOrderRoleEntity", 
                        UtilMisc.toMap("itemMsgInfo", orderId), locale));
            }
            orderHeader = EntityQuery.use(delegator).from("OrderHeader").where("orderId", orderId).queryOne();
            if (orderHeader == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError, 
                        "OrderErrorNoValidOrderHeaderFoundForOrderId", 
                        UtilMisc.toMap("orderId", orderId), locale));
            }
            Timestamp orderCreatedDate = (Timestamp) orderHeader.get("orderDate");
            subContext.put("orderCreatedDate", orderCreatedDate);
            List<GenericValue> orderItemList = orderHeader.getRelated("OrderItem", null, null, false);
            for (GenericValue orderItem: orderItemList) {
                BigDecimal qty = orderItem.getBigDecimal("quantity");
                String productId = orderItem.getString("productId");
                if (UtilValidate.isEmpty(productId)) {
                    continue;
                }
                List<GenericValue> productSubscriptionResourceListFiltered = EntityQuery.use(delegator).from("ProductSubscriptionResource").where("productId", productId).cache(true).filterByDate().queryList();
                if (productSubscriptionResourceListFiltered.size() > 0) {
                    subContext.put("subscriptionTypeId", "PRODUCT_SUBSCR");
                    subContext.put("productId", productId);
                    subContext.put("orderId", orderId);
                    subContext.put("orderItemSeqId", orderItem.get("orderItemSeqId"));
                    subContext.put("inventoryItemId", orderItem.get("fromInventoryItemId"));
                    subContext.put("quantity", Integer.valueOf(qty.intValue()));
                    Map<String, Object> ctx = dctx.getModelService("processExtendSubscriptionByProduct").makeValid(subContext, ModelService.IN_PARAM);
                    Map<String, Object> thisResult = dispatcher.runSync("processExtendSubscriptionByProduct", ctx);
                    if (ServiceUtil.isError(thisResult)) {
                        return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                                "ProductSubscriptionByOrderError", 
                                UtilMisc.toMap("orderId", orderId), locale), null, null, thisResult);
                    }
                }
            }
        } catch (GenericEntityException e) {
            Debug.logError(e.toString(), module);
            return ServiceUtil.returnError(e.toString());
        }

        return ServiceUtil.returnSuccess();
    }
    
    public static Map<String, Object> runServiceOnSubscriptionExpiry( DispatchContext dctx, Map<String, ? extends Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        
        GenericValue userLogin = (GenericValue) context.get("userLogin");        
        Map<String, Object> result = new HashMap<String, Object>();
        Map<String, Object> expiryMap = new HashMap<String, Object>();
        String gracePeriodOnExpiry = null;
        String gracePeriodOnExpiryUomId = null;
        String subscriptionId = null;
        Timestamp expirationCompletedDate = null;
        
        try {
            EntityCondition cond1 = EntityCondition.makeCondition("automaticExtend", EntityOperator.EQUALS, "N");
            EntityCondition cond2 = EntityCondition.makeCondition("automaticExtend", EntityOperator.EQUALS, null);
            EntityCondition cond = EntityCondition.makeCondition(UtilMisc.toList(cond1, cond2), EntityOperator.OR);
            List<GenericValue> subscriptionList = null;
            subscriptionList = EntityQuery.use(delegator).from("Subscription").where(cond).queryList();
            
            if (subscriptionList != null) {
                for (GenericValue subscription : subscriptionList) {
                	expirationCompletedDate = subscription.getTimestamp("expirationCompletedDate");
                	if (expirationCompletedDate == null) {
                		Calendar currentDate = Calendar.getInstance();
                        currentDate.setTime(UtilDateTime.nowTimestamp());
                        // check if the thruDate + grace period (if provided) is earlier than today's date
                        Calendar endDateSubscription = Calendar.getInstance();
                        int field = Calendar.MONTH;
                        String subscriptionResourceId = subscription.getString("subscriptionResourceId");
                        GenericValue subscriptionResource = null;
                        subscriptionResource = EntityQuery.use(delegator).from("SubscriptionResource").where("subscriptionResourceId", subscriptionResourceId).queryOne();
                        subscriptionId = subscription.getString("subscriptionId");
                        gracePeriodOnExpiry = subscription.getString("gracePeriodOnExpiry");
                        gracePeriodOnExpiryUomId = subscription.getString("gracePeriodOnExpiryUomId");
                        String serviceNameOnExpiry = subscriptionResource.getString("serviceNameOnExpiry");
                        endDateSubscription.setTime(subscription.getTimestamp("thruDate"));
                        
                        if (gracePeriodOnExpiry != null && gracePeriodOnExpiryUomId != null) {
                            if ("TF_day".equals(gracePeriodOnExpiryUomId)) {
                                field = Calendar.DAY_OF_YEAR;
                            } else if ("TF_wk".equals(gracePeriodOnExpiryUomId)) {
                                field = Calendar.WEEK_OF_YEAR;
                            } else if ("TF_mon".equals(gracePeriodOnExpiryUomId)) {
                                field = Calendar.MONTH;
                            } else if ("TF_yr".equals(gracePeriodOnExpiryUomId)) {
                                field = Calendar.YEAR;
                            } else {
                                Debug.logWarning("Don't know anything about gracePeriodOnExpiryUomId [" + gracePeriodOnExpiryUomId + "], defaulting to month", module);
                            }
                            endDateSubscription.add(field, Integer.valueOf(gracePeriodOnExpiry).intValue());
                        }
                        if ((currentDate.after(endDateSubscription) || currentDate.equals(endDateSubscription)) && serviceNameOnExpiry != null) {
                            if (userLogin != null) {
                                expiryMap.put("userLogin", userLogin);
                            }
                            if (subscriptionId != null) {
                                expiryMap.put("subscriptionId", subscriptionId);
                            }
                            result = dispatcher.runSync(serviceNameOnExpiry, expiryMap);
                            if (ServiceUtil.isSuccess(result)) {
                                subscription.set("expirationCompletedDate", UtilDateTime.nowTimestamp());
                                delegator.store(subscription);
                                Debug.logInfo("Subscription expired successfully for subscription ID:" + subscriptionId, module);
                            } else if (ServiceUtil.isError(result)) {
                                result = null;
                                Debug.logError("Error expiring subscription while processing with subscriptionId: " + subscriptionId, module);
                            }

                            if (result != null && subscriptionId != null) {
                                Debug.logInfo("Service mentioned in serviceNameOnExpiry called with result: " + result.get("successMessage"), module);
                            } else if (result == null && subscriptionId != null) {
                                Debug.logError("Subscription couldn't be expired for subscriptionId: " + subscriptionId, module);
                                return ServiceUtil.returnError("Subscription couldn't be expired for subscriptionId: " + subscriptionId);
                            }
                        }
                	}
                }
            }
        } catch (GenericServiceException e) {
            Debug.logError("Error while calling service specified in serviceNameOnExpiry", module);
            return ServiceUtil.returnError(e.toString());
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }

        return result;
    }

    public static Map<String, Object> runSubscriptionExpired(
            DispatchContext dctx, Map<String, ? extends Object> context) {
        String subscriptionId = (String) context.get("subscriptionId");
        Map<String, Object> result = new HashMap<String, Object>();
        if (subscriptionId != null) {
            return ServiceUtil.returnSuccess("runSubscriptionExpired service called successfully with subscriptionId " + subscriptionId);
        }
        return result;
    }
}
