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

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilDateTime;
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.condition.EntityCondition;
import org.ofbiz.entity.condition.EntityOperator;
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.ebay.sdk.ApiContext;
import com.ebay.sdk.ApiException;
import com.ebay.sdk.SdkException;
import com.ebay.sdk.SdkSoapException;
import com.ebay.sdk.call.AddDisputeCall;
import com.ebay.sdk.call.AddItemCall;
import com.ebay.sdk.call.AddOrderCall;
import com.ebay.sdk.call.DeleteSellingManagerTemplateCall;
import com.ebay.sdk.call.GetBestOffersCall;
import com.ebay.sdk.call.GetItemCall;
import com.ebay.sdk.call.GetMyeBaySellingCall;
import com.ebay.sdk.call.GetSellingManagerInventoryCall;
import com.ebay.sdk.call.GetSellingManagerSoldListingsCall;
import com.ebay.sdk.call.GetUserCall;
import com.ebay.sdk.call.LeaveFeedbackCall;
import com.ebay.sdk.call.RelistItemCall;
import com.ebay.sdk.call.RespondToBestOfferCall;
import com.ebay.sdk.call.VerifyAddSecondChanceItemCall;
import com.ebay.soap.eBLBaseComponents.AddOrderRequestType;
import com.ebay.soap.eBLBaseComponents.AddOrderResponseType;
import com.ebay.soap.eBLBaseComponents.AmountType;
import com.ebay.soap.eBLBaseComponents.AutomatedLeaveFeedbackEventCodeType;
import com.ebay.soap.eBLBaseComponents.BestOfferActionCodeType;
import com.ebay.soap.eBLBaseComponents.BestOfferDetailsType;
import com.ebay.soap.eBLBaseComponents.BestOfferStatusCodeType;
import com.ebay.soap.eBLBaseComponents.BestOfferType;
import com.ebay.soap.eBLBaseComponents.BuyerPaymentMethodCodeType;
import com.ebay.soap.eBLBaseComponents.CommentTypeCodeType;
import com.ebay.soap.eBLBaseComponents.CurrencyCodeType;
import com.ebay.soap.eBLBaseComponents.DeleteSellingManagerTemplateRequestType;
import com.ebay.soap.eBLBaseComponents.DeleteSellingManagerTemplateResponseType;
import com.ebay.soap.eBLBaseComponents.DetailLevelCodeType;
import com.ebay.soap.eBLBaseComponents.DisputeExplanationCodeType;
import com.ebay.soap.eBLBaseComponents.DisputeReasonCodeType;
import com.ebay.soap.eBLBaseComponents.FeedbackDetailType;
import com.ebay.soap.eBLBaseComponents.GetSellingManagerInventoryRequestType;
import com.ebay.soap.eBLBaseComponents.GetSellingManagerInventoryResponseType;
import com.ebay.soap.eBLBaseComponents.ItemArrayType;
import com.ebay.soap.eBLBaseComponents.ItemListCustomizationType;
import com.ebay.soap.eBLBaseComponents.ItemSortTypeCodeType;
import com.ebay.soap.eBLBaseComponents.ItemType;
import com.ebay.soap.eBLBaseComponents.ListingTypeCodeType;
import com.ebay.soap.eBLBaseComponents.OrderType;
import com.ebay.soap.eBLBaseComponents.PaginatedItemArrayType;
import com.ebay.soap.eBLBaseComponents.PaginationType;
import com.ebay.soap.eBLBaseComponents.SellingManagerOrderStatusType;
import com.ebay.soap.eBLBaseComponents.SellingManagerPaidStatusCodeType;
import com.ebay.soap.eBLBaseComponents.SellingManagerProductDetailsType;
import com.ebay.soap.eBLBaseComponents.SellingManagerProductType;
import com.ebay.soap.eBLBaseComponents.SellingManagerShippedStatusCodeType;
import com.ebay.soap.eBLBaseComponents.SellingManagerSoldOrderType;
import com.ebay.soap.eBLBaseComponents.SellingManagerSoldTransactionType;
import com.ebay.soap.eBLBaseComponents.SellingManagerTemplateDetailsArrayType;
import com.ebay.soap.eBLBaseComponents.SellingManagerTemplateDetailsType;
import com.ebay.soap.eBLBaseComponents.TradingRoleCodeType;
import com.ebay.soap.eBLBaseComponents.TransactionArrayType;
import com.ebay.soap.eBLBaseComponents.TransactionType;
import com.ebay.soap.eBLBaseComponents.UserType;

public class EbayStoreAutoPreferences {
    public static String module = EbayStoreAutoPreferences.class.getName();
    private static final String resource = "EbayStoreUiLabels";

    public EbayStoreAutoPreferences() {

    }

    /*  It may take several minutes to process your automated feedback.  to connect to ebay site*/
    public static Map<String, Object> autoPrefLeaveFeedbackOption(DispatchContext dctx, Map<String, ? extends Object> context) throws ApiException, SdkException, Exception {

        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");

        if (UtilValidate.isEmpty(context.get("productStoreId")) && UtilValidate.isEmpty(context.get("jobId"))) {
            return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, "EbayStoreRequiredProductStoreId", locale));
        }
        String jobId = (String) context.get("jobId");
        String productStoreId = (String) context.get("productStoreId");
        String isAutoPositiveFeedback = "N";
        String feedbackEventCode = null;
        GenericValue ebayProductStorePref = null;
        List<String> list = FastList.newInstance();

        try {
            ApiContext apiContext = EbayStoreHelper.getApiContext(productStoreId, locale, delegator);
            ebayProductStorePref = delegator.findByPrimaryKey("EbayProductStorePref", UtilMisc.toMap("productStoreId", productStoreId, "autoPrefEnumId", "EBAY_AUTO_PIT_FB"));
            if (UtilValidate.isNotEmpty(ebayProductStorePref) && UtilValidate.isNotEmpty(ebayProductStorePref.getString("autoPrefJobId"))) {
                isAutoPositiveFeedback = ebayProductStorePref.getString("enabled");
                // if isAutoPositiveFeedback is N that means not start this job run service
                if ("Y".equals(isAutoPositiveFeedback) && jobId.equals(ebayProductStorePref.getString("autoPrefJobId"))) {
                    feedbackEventCode = ebayProductStorePref.getString("condition1");
                    String storeComments = ebayProductStorePref.getString("condition2");
                    String comment = null;
                    if (UtilValidate.isNotEmpty(storeComments)) {
                        if (storeComments.indexOf("\\[,\\]") != -1) {
                            String[] strs = storeComments.split("\\[,\\]");
                            for (String str : strs) {
                                list.add(str);
                            }
                        }
                    }
                    // start getting sold item list from ebay follow your site
                    GetSellingManagerSoldListingsCall sellingManagerSoldListings = new GetSellingManagerSoldListingsCall(apiContext);

                    List<SellingManagerSoldOrderType> items = FastList.newInstance();
                    SellingManagerSoldOrderType[] sellingManagerSoldOrders = sellingManagerSoldListings.getSellingManagerSoldListings();
                    if (UtilValidate.isNotEmpty(sellingManagerSoldOrders)) {
                        for (SellingManagerSoldOrderType solditem : sellingManagerSoldOrders) {
                            SellingManagerOrderStatusType orderStatus = solditem.getOrderStatus();
                            if (orderStatus != null && !orderStatus.isFeedbackSent()) {
                                SellingManagerPaidStatusCodeType paidStatus = orderStatus.getPaidStatus();
                                CommentTypeCodeType commentType = orderStatus.getFeedbackReceived();
                                //Buyer has paid for this item.
                                if ("PAYMENT_RECEIVED".equals(feedbackEventCode) && SellingManagerPaidStatusCodeType.PAID.equals(paidStatus)) {
                                    items.add(solditem);
                                }
                                //Buyer has paid for this item and left me positive feedback.
                                if ("POSITIVE_FEEDBACK_RECEIVED".equals(feedbackEventCode) && CommentTypeCodeType.POSITIVE.equals(commentType) && SellingManagerPaidStatusCodeType.PAID.equals(paidStatus)) {
                                    items.add(solditem);
                                }
                            }
                        }
                        GetUserCall getUserCall = new GetUserCall(apiContext);
                        String commentingUser = getUserCall.getUser().getUserID();
                        for (SellingManagerSoldOrderType item : items) {
                            // start leave feedbacks
                            SellingManagerSoldTransactionType[] soldTrans = item.getSellingManagerSoldTransaction();
                            if (UtilValidate.isNotEmpty(soldTrans)) {
                                for (SellingManagerSoldTransactionType soldTran : soldTrans) {
                                    LeaveFeedbackCall leaveFeedbackCall = new LeaveFeedbackCall(apiContext);
                                    FeedbackDetailType detail = new FeedbackDetailType();
                                    // ramdom comments
                                    if (list.size() > 0) {
                                        Collections.shuffle(list, new Random());
                                        comment = list.get(0);
                                    }
                                    detail.setCommentText(comment);
                                    detail.setCommentingUser(commentingUser);
                                    //detail.setCommentingUserScore(value);
                                    detail.setCommentType(CommentTypeCodeType.POSITIVE);
                                    detail.setItemID(soldTran.getItemID());
                                    detail.setItemPrice(soldTran.getItemPrice());
                                    detail.setItemTitle(soldTran.getItemTitle());
                                    leaveFeedbackCall.setFeedbackDetail(detail);
                                    leaveFeedbackCall.setTargetUser(item.getBuyerID());
                                    leaveFeedbackCall.setTransactionID(String.valueOf(soldTran.getTransactionID()));
                                    leaveFeedbackCall.leaveFeedback();
                                    Debug.logInfo("Auto leave feedback with site ".concat(apiContext.getSite().value()).concat("itemId ".concat(soldTran.getItemID())).concat(" comment is ".concat(comment)), module);
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, "EbayStoreProblemConnectingToEbaySite", locale) + e);
        }

        return ServiceUtil.returnSuccess();
    }

    public static String autoPrefLeaveFeedbackOptions(HttpServletRequest request, HttpServletResponse response) {
        LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
        Delegator delegator = (Delegator) request.getAttribute("delegator");
        Locale locale = UtilHttp.getLocale(request);
        Map<String, Object> paramMap = UtilHttp.getCombinedMap(request);

        if (UtilValidate.isEmpty(paramMap.get("productStoreId"))) {
            request.setAttribute("_ERROR_MESSAGE_", "Required productStoreId for get api context to connect with ebay site.");
            return "error";
        }

        String productStoreId = (String) paramMap.get("productStoreId");
        String isAutoPositiveFeedback = "N";
        String condition = null;
        if (UtilValidate.isNotEmpty(paramMap.get("isAutoPositiveFeedback"))) {
            isAutoPositiveFeedback = (String) paramMap.get("isAutoPositiveFeedback");
        }
        String feedbackEventCode = (String) paramMap.get("feedbackEventCode");
        ApiContext apiContext = EbayStoreHelper.getApiContext(productStoreId, locale, delegator);

        try {
            GenericValue ebayProductStorePref = null;
            String comments = null;
            String autoPrefJobId = null;
            GenericValue userLogin = delegator.findOne("UserLogin", false, "userLoginId", "system");
            if ("Y".equals(isAutoPositiveFeedback)) {
                if ("PAYMENT_RECEIVED".equals(feedbackEventCode)) {
                    condition = AutomatedLeaveFeedbackEventCodeType.PAYMENT_RECEIVED.toString();
                } else if ("POSITIVE_FEEDBACK_RECEIVED".equals(feedbackEventCode)) {
                    condition = AutomatedLeaveFeedbackEventCodeType.POSITIVE_FEEDBACK_RECEIVED.toString();
                }
                // allow only 10 comment can be store / set new comments to condition2 separate by [,]
            }
            for (int i = 1; i <= 5; i++) {
                String comment = (String) paramMap.get("comment_".concat(String.valueOf(i)));
                if (comment != null && comment.length() > 0) {
                    if (comments == null) {
                        comments = comment;
                    } else {
                        comments = comments.concat("[").concat(",").concat(("]").concat(comment));
                    }
                }
            }
            if (UtilValidate.isEmpty(comments)) {
                request.setAttribute("_ERROR_MESSAGE_", "Required least one at comment for your store feedback send with ebay site.");
                return "error";
            }

            Map<String, Object> context = UtilMisc.<String, Object>toMap("userLogin", userLogin, "serviceName", "autoPrefLeaveFeedbackOption");
            ebayProductStorePref = delegator.findByPrimaryKey("EbayProductStorePref", UtilMisc.toMap("productStoreId", productStoreId, "autoPrefEnumId", "EBAY_AUTO_PIT_FB"));
            context.put("productStoreId", productStoreId);
            context.put("autoPrefEnumId", "EBAY_AUTO_PIT_FB");
            if (UtilValidate.isNotEmpty(ebayProductStorePref) && UtilValidate.isNotEmpty(ebayProductStorePref.getString("autoPrefJobId"))) {
                autoPrefJobId = ebayProductStorePref.getString("autoPrefJobId");
            }
            context.put("autoPrefJobId", autoPrefJobId);
            context.put("enabled", isAutoPositiveFeedback);
            context.put("condition1", condition);
            context.put("condition2", comments);
            context.put("condition3", null);
            if (UtilValidate.isEmpty(ebayProductStorePref)) {
                dispatcher.runSync("createEbayProductStorePref", context);
            } else {
                dispatcher.runSync("updateEbayProductStorePref", context);
            }
            request.setAttribute("_EVENT_MESSAGE_", "Setting Automated Positive Feedback for Buyers Success with site " + apiContext.getSite().value());

        } catch (GenericEntityException e) {
            request.setAttribute("_ERROR_MESSAGE_", e.getMessage());
            return "error";
        } catch (GenericServiceException e) {
            request.setAttribute("_ERROR_MESSAGE_", e.getMessage());
            return "error";
        }

        return "success";
    }

    /* start automatically service send a Feedback Reminder email if feedback has not been received. and check how many days after shipping you want this email sent? */
    public static Map<String, Object> autoSendFeedbackReminderEmail(DispatchContext dctx, Map<String, ? extends Object> context) throws ApiException, SdkException, Exception {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Locale locale = (Locale) context.get("locale");
        GenericValue userLogin = delegator.findOne("UserLogin", false, "userLoginId", "system");
        if (UtilValidate.isEmpty(context.get("productStoreId")) && UtilValidate.isEmpty(context.get("jobId"))) {
            return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, "EbayStoreRequiredProductStoreId", locale));
        }
        String jobId = (String) context.get("jobId");
        String productStoreId = (String) context.get("productStoreId");
        String isAutoFeedbackReminder = "N";
        int afterDays = 0;
        GenericValue ebayProductStorePref = null;
        String dateTimeFormat = UtilDateTime.DATE_TIME_FORMAT;
        SimpleDateFormat formatter = new SimpleDateFormat(dateTimeFormat);

        try {
            ApiContext apiContext = EbayStoreHelper.getApiContext(productStoreId, locale, delegator);
            ebayProductStorePref = delegator.findByPrimaryKey("EbayProductStorePref", UtilMisc.toMap("productStoreId", productStoreId, "autoPrefEnumId", "EBAY_AUTO_FB_RMD"));
            if (UtilValidate.isNotEmpty(ebayProductStorePref) && UtilValidate.isNotEmpty(ebayProductStorePref.getString("autoPrefJobId"))) {
                isAutoFeedbackReminder = ebayProductStorePref.getString("enabled");
                // if isAutoPositiveFeedback is N that means not start this job run service
                if ("Y".equals(isAutoFeedbackReminder) && jobId.equals(ebayProductStorePref.getString("autoPrefJobId"))) {
                    afterDays = Integer.parseInt(ebayProductStorePref.getString("condition1"));
                    
                    // start getting sold item list from ebay follow your site
                    GetSellingManagerSoldListingsCall sellingManagerSoldListings = new GetSellingManagerSoldListingsCall(apiContext);
                    List<SellingManagerSoldOrderType> items = FastList.newInstance();
                    SellingManagerSoldOrderType[] sellingManagerSoldOrders = sellingManagerSoldListings.getSellingManagerSoldListings();
                    if (UtilValidate.isNotEmpty(sellingManagerSoldOrders)) {
                        for (SellingManagerSoldOrderType solditem : sellingManagerSoldOrders) {
                            SellingManagerOrderStatusType orderStatus = solditem.getOrderStatus();
                            if (orderStatus != null) {
                                SellingManagerPaidStatusCodeType paidStatus = orderStatus.getPaidStatus();
                                SellingManagerShippedStatusCodeType shippedStatus = orderStatus.getShippedStatus();

                                //Buyer has paid for this item.  && Seller shipped items but feedback has not been received from buyer more than days condition
                                if (SellingManagerPaidStatusCodeType.PAID.equals(paidStatus) && SellingManagerShippedStatusCodeType.SHIPPED.equals(shippedStatus)) {
                                    Calendar right_now = Calendar.getInstance();
                                    Calendar shippedTime = orderStatus.getShippedTime();
                                    Calendar afterShippedTime = orderStatus.getShippedTime();
                                    afterShippedTime.add(Calendar.DAY_OF_MONTH, afterDays);
                                    Debug.logInfo("Verify date for send reminder feedback eamil by auto service: buyer " + solditem.getBuyerID() + " seller shippedTime " +
                                            "" + formatter.format(shippedTime) + " codition days " + afterDays + " after shippedTime :" + formatter.format(afterShippedTime) + " now date" + formatter.format(right_now), module);
                                    // if now date is after shipped time follow after days condition would be send reminder email to buyer
                                    if (right_now.after(afterShippedTime)) {
                                        items.add(solditem);
                                    }
                                }
                            }
                        }

                        // call service send email (get template follow productStoreId)
                        for (SellingManagerSoldOrderType item : items) {
                            // call send
                            Map<String, Object> sendMap = FastMap.newInstance();
                            GenericValue productStoreEmail = delegator.findByPrimaryKey("OldProdStoreEmailSetting", UtilMisc.toMap("productStoreId", productStoreId, "emailType", "EBAY_FEEBACK_REMIN"));
                            String bodyScreenLocation = productStoreEmail.getString("bodyScreenLocation");
                            sendMap.put("bodyScreenUri", bodyScreenLocation);
                            String subjectString = productStoreEmail.getString("subject");
                            sendMap.put("userLogin", userLogin);
                            sendMap.put("subject", subjectString);
                            sendMap.put("contentType", productStoreEmail.get("contentType"));
                            sendMap.put("sendFrom", productStoreEmail.get("fromAddress"));
                            sendMap.put("sendCc", productStoreEmail.get("ccAddress"));
                            sendMap.put("sendBcc", productStoreEmail.get("bccAddress"));
                            sendMap.put("sendTo", item.getBuyerEmail());

                            Map<String, Object> bodyParameters = FastMap.newInstance();
                            bodyParameters.put("buyerUserId", item.getBuyerID());
                            sendMap.put("bodyParameters", bodyParameters);

                            try {
                                dispatcher.runAsync("sendMailFromScreen", sendMap);
                            } catch (Exception e) {
                                Debug.logError(e, module);
                                return ServiceUtil.returnError(e.getMessage());
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, "EbayStoreProblemConnectingToEbaySite", locale) + e);
        }

        return ServiceUtil.returnSuccess();
    }

    public static Map<String, Object> automaticEbayRelistSoldItems(DispatchContext dctx, Map<String, ? extends Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        String jobId = (String) context.get("jobId");
        try {
            GenericValue userLogin = delegator.findOne("UserLogin", false, "userLoginId", "system");
            Map<String, Object> serviceMap = FastMap.newInstance();
            serviceMap.put("userLogin", userLogin);
            //ProductStore
            List<GenericValue> productStores = delegator.findByAnd("EbayProductStorePref", UtilMisc.toMap("autoPrefJobId", jobId));
            if (productStores.size() != 0) {
                // get auto preference setting
                String productStoreId = productStores.get(0).getString("productStoreId");
                String condition1 = productStores.get(0).getString("condition1");
                String condition2 = productStores.get(0).getString("condition2");
                // convert preference setting
                Timestamp fromDate = UtilDateTime.toTimestamp(condition1);
                Timestamp thruDate = UtilDateTime.toTimestamp(condition2);
                Timestamp nowTime = UtilDateTime.nowTimestamp();
                if (nowTime.after(fromDate) && nowTime.before(thruDate)) {
                    serviceMap.put("productStoreId", productStoreId);
                    Map<String, Object> eBayUserLogin = dispatcher.runSync("getEbayStoreUser", serviceMap);
                    String eBayUserLoginId = (String) eBayUserLogin.get("userLoginId");
                    GenericValue party = delegator.findByPrimaryKey("UserLogin", UtilMisc.toMap("userLoginId", eBayUserLoginId));
                    String partyId = party.getString("partyId");
                    //save sold items to OFbBiz product entity
                    Map<String, Object> resultService = dispatcher.runSync("getEbaySoldItems", serviceMap);
                    List<Map<String, Object>> soldItems = UtilGenerics.checkList(resultService.get("soldItems"));
                    if (soldItems.size() != 0) {
                        for (int itemCount = 0; itemCount < soldItems.size(); itemCount++) {
                            Map<String, Object> soldItemMap = soldItems.get(itemCount);
                            if (UtilValidate.isNotEmpty(soldItemMap.get("itemId"))) {
                                GenericValue productCheck = delegator.findByPrimaryKey("Product", UtilMisc.toMap("productId", soldItemMap.get("itemId")));
                                if (productCheck == null) {
                                    Map<String, Object> inMap = FastMap.newInstance();
                                    inMap.put("productId", soldItemMap.get("itemId"));
                                    inMap.put("productTypeId", "EBAY_ITEM");
                                    inMap.put("internalName", "eBay Item " + soldItemMap.get("title"));
                                    inMap.put("userLogin", userLogin);
                                    dispatcher.runSync("createProduct", inMap);
                                    // ProductRole (VENDOR)
                                    List<GenericValue> productRole = delegator.findByAnd("ProductRole", UtilMisc.toMap("partyId", partyId, "productId", soldItemMap.get("itemId"), "roleTypeId", "VENDOR"));
                                    if (productRole.size() == 0) {
                                        Map<String, Object> addRole = FastMap.newInstance();
                                        addRole.put("productId", soldItemMap.get("itemId"));
                                        addRole.put("roleTypeId", "VENDOR");
                                        addRole.put("partyId", partyId);
                                        addRole.put("fromDate", UtilDateTime.nowTimestamp());
                                        addRole.put("userLogin", userLogin);
                                        dispatcher.runSync("addPartyToProduct", addRole);
                                    }
                                }
                            }
                        }
                    }
                    //check active items
                    serviceMap = FastMap.newInstance();
                    serviceMap.put("userLogin", userLogin);
                    serviceMap.put("productStoreId", productStoreId);
                    resultService = dispatcher.runSync("getEbayActiveItems", serviceMap);
                    List<Map<String, Object>> activeItems = UtilGenerics.checkList(resultService.get("activeItems"));
                    List<String> activeItemMaps = FastList.newInstance();
                    if (activeItems.size() != 0) {
                        for (int itemCount = 0; itemCount < activeItems.size(); itemCount++) {
                            Map<String, Object> activeItemMap = UtilGenerics.checkMap(activeItems.get(itemCount));
                            if (UtilValidate.isNotEmpty(activeItemMap.get("itemId"))) {
                                activeItemMaps.add((String) activeItemMap.get("itemId"));
                            }
                        }
                    }
                    //check product role
                    List<GenericValue> productRoles = delegator.findByAnd("ProductRole", UtilMisc.toMap("partyId", partyId, "roleTypeId", "VENDOR"));
                    List<String> productRoleIds = FastList.newInstance();
                    if (productRoles.size() != 0) {
                        for (int itemCount = 0; itemCount < productRoles.size(); itemCount++) {
                            String productId = productRoles.get(itemCount).getString("productId");
                            productRoleIds.add(productId);
                        }
                    }
                    List<EntityCondition> andExpr = FastList.newInstance();
                    EntityCondition activeItemCond = EntityCondition.makeCondition("productId", EntityOperator.NOT_IN, activeItemMaps);
                    andExpr.add(activeItemCond);
                    EntityCondition productTypeCond = EntityCondition.makeCondition("productTypeId", EntityOperator.EQUALS, "EBAY_ITEM");
                    andExpr.add(productTypeCond);
                    EntityCondition isVirtualCond = EntityCondition.makeCondition("isVirtual", EntityOperator.NOT_EQUAL, "Y");
                    andExpr.add(isVirtualCond);
                    EntityCondition productRole = EntityCondition.makeCondition("productId", EntityOperator.IN, productRoleIds);
                    andExpr.add(productRole);
                    EntityCondition andCond = EntityCondition.makeCondition(andExpr, EntityOperator.AND);
                    List<GenericValue> itemsToRelist = delegator.findList("Product", andCond, null, null, null, false);
                    if (itemsToRelist.size() != 0) {
                        //re-list sold items and not active
                        ApiContext apiContext = EbayStoreHelper.getApiContext(productStoreId, locale, delegator);
                        for (int itemRelist = 0; itemRelist < itemsToRelist.size(); itemRelist++) {
                            RelistItemCall relistItemCall = new RelistItemCall(apiContext);
                            ItemType itemToBeRelisted = new ItemType();
                            GenericValue product = itemsToRelist.get(itemRelist);
                            itemToBeRelisted.setItemID(product.getString("productId"));
                            relistItemCall.setItemToBeRelisted(itemToBeRelisted);
                            relistItemCall.relistItem();
                            GenericValue productStore = delegator.findByPrimaryKey("Product", UtilMisc.toMap("productId", product.getString("productId")));
                            productStore.set("isVirtual", "Y");
                            productStore.store();
                            Debug.logInfo("Relisted Item - " + product.getString("productId"), module);
                        }
                    }
                }
            }
        } catch (Exception e) {
            return ServiceUtil.returnError(e.getMessage());
        }
        return ServiceUtil.returnSuccess();
    }

    public static Map<String, Object> automaticEbayDisputeNotComplete(DispatchContext dctx, Map<String, ? extends Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        String jobId = (String) context.get("jobId");
        try {
            GenericValue userLogin = delegator.findOne("UserLogin", false, "userLoginId", "system");
            List<GenericValue> productStores = delegator.findByAnd("EbayProductStorePref", UtilMisc.toMap("autoPrefJobId", jobId));
            if (productStores.size() != 0) {
                // get automatic setting
                String productStoreId = productStores.get(0).getString("productStoreId");
                String condition1 = productStores.get(0).getString("condition1");
                String condition2 = productStores.get(0).getString("condition2");
                String condition3 = productStores.get(0).getString("condition3");
                // convert automatic setting for usage
                int afterDays = 0;
                if (UtilValidate.isInteger(condition1)) {
                    afterDays = Integer.parseInt(condition1);
                }
                DisputeReasonCodeType disputeReason = null;
                if (UtilValidate.isNotEmpty(condition2)) {
                    disputeReason = DisputeReasonCodeType.valueOf(condition2);
                }
                DisputeExplanationCodeType disputeExplanation = null;
                if (UtilValidate.isNotEmpty(condition3)) {
                    disputeExplanation = DisputeExplanationCodeType.valueOf(condition3);
                }
                // get sold items
                Map<String, Object> serviceMap = FastMap.newInstance();
                serviceMap.put("productStoreId", productStoreId);
                serviceMap.put("userLogin", userLogin);
                Map<String, Object> resultService = dispatcher.runSync("getEbaySoldItems", serviceMap);
                List<Map<String, Object>> soldItems = UtilGenerics.checkList(resultService.get("soldItems"));
                // check items to dispute
                List<Map<String, Object>> itemsToDispute = FastList.newInstance();
                for (int itemCount = 0; itemCount < soldItems.size(); itemCount++) {
                    Map<String, Object> item = UtilGenerics.checkMap(soldItems.get(itemCount));
                    String checkoutStatus = (String) item.get("checkoutStatus");
                    Date creationTime = (Date) item.get("creationTime");
                    Date paidTime = (Date) item.get("paidTime");
                    String unpaidItemStatus = (String) item.get("unpaidItemStatus");
                    int checkDays = UtilDateTime.getIntervalInDays(UtilDateTime.toTimestamp(creationTime), UtilDateTime.nowTimestamp());
                    if (checkDays > afterDays && "CheckoutIncomplete".equals(checkoutStatus) && unpaidItemStatus == null && paidTime == null && checkoutStatus != "CheckoutComplete") {
                        itemsToDispute.add(item);
                    }
                }
                // Dispute items
                if (disputeReason != null && disputeExplanation != null && itemsToDispute.size() != 0) {
                    ApiContext apiContext = EbayStoreHelper.getApiContext(productStoreId, locale, delegator);
                    DetailLevelCodeType[] detailLevels = new DetailLevelCodeType[]{
                            DetailLevelCodeType.RETURN_ALL,
                            DetailLevelCodeType.ITEM_RETURN_ATTRIBUTES,
                            DetailLevelCodeType.ITEM_RETURN_DESCRIPTION
                    };
                    for (int count = 0; count < itemsToDispute.size(); count++) {
                        Map<String, Object> item = itemsToDispute.get(count);
                        AddDisputeCall api = new AddDisputeCall(apiContext);
                        api.setDetailLevel(detailLevels);
                        api.setItemID((String) item.get("itemId"));
                        api.setTransactionID((String) item.get("transactionId"));
                        api.setDisputeExplanation(disputeExplanation);
                        api.setDisputeReason(disputeReason);
                    }
                }
            }
        } catch (Exception e) {
            return ServiceUtil.returnError(e.getMessage());
        }
        return ServiceUtil.returnSuccess();
    }

    public static Map<String, Object> automaticEbayDisputeNotPay(DispatchContext dctx, Map<String, ? extends Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        String jobId = (String) context.get("jobId");
        try {
            GenericValue userLogin = delegator.findOne("UserLogin", false, "userLoginId", "system");
            List<GenericValue> productStores = delegator.findByAnd("EbayProductStorePref", UtilMisc.toMap("autoPrefJobId", jobId));
            if (productStores.size() != 0) {
                // get automatic setting
                String productStoreId = productStores.get(0).getString("productStoreId");
                String condition1 = productStores.get(0).getString("condition1");
                String condition2 = productStores.get(0).getString("condition2");
                String condition3 = productStores.get(0).getString("condition3");
                // convert automatic setting for usage
                int afterDays = 0;
                if (UtilValidate.isInteger(condition1)) {
                    afterDays = Integer.parseInt(condition1);
                }
                DisputeReasonCodeType disputeReason = null;
                if (UtilValidate.isNotEmpty(condition2)) {
                    disputeReason = DisputeReasonCodeType.valueOf(condition2);
                }
                DisputeExplanationCodeType disputeExplanation = null;
                if (UtilValidate.isNotEmpty(condition3)) {
                    disputeExplanation = DisputeExplanationCodeType.valueOf(condition3);
                }
                // get sold items
                Map<String, Object> serviceMap = FastMap.newInstance();
                serviceMap.put("productStoreId", productStoreId);
                serviceMap.put("userLogin", userLogin);
                Map<String, Object> resultService = dispatcher.runSync("getEbaySoldItems", serviceMap);
                List<Map<String, Object>> soldItems = UtilGenerics.checkList(resultService.get("soldItems"));
                // check items to dispute
                List<Map<String, Object>> itemsToDispute = FastList.newInstance();
                for (int itemCount = 0; itemCount < soldItems.size(); itemCount++) {
                    Map<String, Object> item = UtilGenerics.checkMap(soldItems.get(itemCount));
                    String checkoutStatus = (String) item.get("checkoutStatus");
                    Date creationTime = (Date) item.get("creationTime");
                    Date paidTime = (Date) item.get("paidTime");
                    String unpaidItemStatus = (String) item.get("unpaidItemStatus");
                    int checkDays = UtilDateTime.getIntervalInDays(UtilDateTime.toTimestamp(creationTime), UtilDateTime.nowTimestamp());
                    if (checkDays > afterDays && unpaidItemStatus == null && paidTime == null && checkoutStatus == "CheckoutComplete") {
                        itemsToDispute.add(item);
                    }
                }
                // Dispute items
                if (disputeReason != null && disputeExplanation != null && itemsToDispute.size() != 0) {
                    ApiContext apiContext = EbayStoreHelper.getApiContext(productStoreId, locale, delegator);
                    DetailLevelCodeType[] detailLevels = new DetailLevelCodeType[]{
                            DetailLevelCodeType.RETURN_ALL,
                            DetailLevelCodeType.ITEM_RETURN_ATTRIBUTES,
                            DetailLevelCodeType.ITEM_RETURN_DESCRIPTION
                    };
                    for (int count = 0; count < itemsToDispute.size(); count++) {
                        Map<String, Object> item = itemsToDispute.get(count);
                        AddDisputeCall api = new AddDisputeCall(apiContext);
                        api.setDetailLevel(detailLevels);
                        api.setItemID((String) item.get("itemId"));
                        api.setTransactionID((String) item.get("transactionId"));
                        api.setDisputeExplanation(disputeExplanation);
                        api.setDisputeReason(disputeReason);
                    }
                }
            }
        } catch (Exception e) {
            return ServiceUtil.returnError(e.getMessage());
        }
        return ServiceUtil.returnSuccess();
    }

    /* start automatically service send an email when ebay seller has been received payment from ebay buyer */
    public static Map<String, Object> autoSendPaymentReceivedEmail(DispatchContext dctx, Map<String, ? extends Object> context) throws ApiException, SdkException, Exception {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Locale locale = (Locale) context.get("locale");
        GenericValue userLogin = delegator.findOne("UserLogin", false, "userLoginId", "system");

        if (UtilValidate.isEmpty(context.get("productStoreId")) && UtilValidate.isEmpty(context.get("jobId"))) {
            return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, "EbayStoreRequiredProductStoreId", locale));
        }

        String jobId = (String) context.get("jobId");
        String productStoreId = (String) context.get("productStoreId");

        String isAutoSendEmail = "N";
        GenericValue ebayProductStorePref = null;

        try {
            ApiContext apiContext = EbayStoreHelper.getApiContext(productStoreId, locale, delegator);
            ebayProductStorePref = delegator.findByPrimaryKey("EbayProductStorePref", UtilMisc.toMap("productStoreId", productStoreId, "autoPrefEnumId", "EBAY_AUTO_FB_RMD"));
            if (UtilValidate.isNotEmpty(ebayProductStorePref) && UtilValidate.isNotEmpty(ebayProductStorePref.getString("autoPrefJobId"))) {
                isAutoSendEmail = ebayProductStorePref.getString("enabled");
                // if isAutoPositiveFeedback is N that means not start this job run service
                if ("Y".equals(isAutoSendEmail) && jobId.equals(ebayProductStorePref.getString("autoPrefJobId"))) {
                    // start getting sold item list from ebay follow your site
                    GetSellingManagerSoldListingsCall sellingManagerSoldListings = new GetSellingManagerSoldListingsCall(apiContext);
                    List<SellingManagerSoldOrderType> items = FastList.newInstance();
                    SellingManagerSoldOrderType[] sellingManagerSoldOrders = sellingManagerSoldListings.getSellingManagerSoldListings();
                    if (UtilValidate.isNotEmpty(sellingManagerSoldOrders)) {
                        for (SellingManagerSoldOrderType solditem : sellingManagerSoldOrders) {
                            SellingManagerOrderStatusType orderStatus = solditem.getOrderStatus();
                            if (orderStatus != null) {
                                SellingManagerPaidStatusCodeType paidStatus = orderStatus.getPaidStatus();
                                //Buyer has paid for this item. and seller received
                                if (SellingManagerPaidStatusCodeType.PAID.equals(paidStatus)) {
                                    items.add(solditem);
                                }
                            }
                        }

                        // call service send email (get template follow productStoreId)
                        for (SellingManagerSoldOrderType item : items) {
                            // call send
                            Map<String, Object> sendMap = FastMap.newInstance();
                            GenericValue productStoreEmail = delegator.findByPrimaryKey("OldProdStoreEmailSetting", UtilMisc.toMap("productStoreId", productStoreId, "emailType", "EBAY_PAY_RECIEVED"));
                            String bodyScreenLocation = productStoreEmail.getString("bodyScreenLocation");
                            sendMap.put("bodyScreenUri", bodyScreenLocation);
                            String subjectString = productStoreEmail.getString("subject");
                            sendMap.put("userLogin", userLogin);
                            sendMap.put("subject", subjectString);
                            sendMap.put("contentType", productStoreEmail.get("contentType"));
                            sendMap.put("sendFrom", productStoreEmail.get("fromAddress"));
                            sendMap.put("sendCc", productStoreEmail.get("ccAddress"));
                            sendMap.put("sendBcc", productStoreEmail.get("bccAddress"));
                            sendMap.put("sendTo", item.getBuyerEmail());

                            Map<String, Object> bodyParameters = FastMap.newInstance();
                            bodyParameters.put("buyerUserId", item.getBuyerID());
                            sendMap.put("bodyParameters", bodyParameters);

                            try {
                                dispatcher.runAsync("sendMailFromScreen", sendMap);
                            } catch (Exception e) {
                                Debug.logError(e, module);
                                return ServiceUtil.returnError(e.getMessage());
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, "EbayStoreProblemConnectingToEbaySite", locale) + e);
        }

        return ServiceUtil.returnSuccess();
    }


    public static Map<String, Object> runCombineOrders(DispatchContext dctx, Map<String, Object> context) {
        Map<String, Object> result = FastMap.newInstance();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        String productStoreId = (String) context.get("productStoreId");
        try {
            GenericValue userLogin = delegator.findOne("UserLogin", false, "userLoginId", "system");
            ApiContext apiContext = EbayStoreHelper.getApiContext(productStoreId, locale, delegator);
            GetSellingManagerSoldListingsCall sellingManagerSoldListings = new GetSellingManagerSoldListingsCall(apiContext);
            SellingManagerSoldOrderType[] sellingManagerSoldOrders = sellingManagerSoldListings.getSellingManagerSoldListings();
            if (sellingManagerSoldOrders != null) {
                int soldOrderLength = sellingManagerSoldOrders.length;
                GenericValue ebayPref = delegator.findByPrimaryKey("EbayProductStorePref", UtilMisc.toMap("productStoreId", productStoreId, "autoPrefEnumId", "ENA_COMB_ORD"));
                if (UtilValidate.isNotEmpty(ebayPref)) {

                    Timestamp beginDate = UtilDateTime.toTimestamp("01/01/2001 00:00:00");
                    Long daysCount = Long.parseLong(ebayPref.get("condition1").toString());
                    Hashtable<String, List<Map<String, Object>>> h = new Hashtable<String, List<Map<String, Object>>>();

                    for (int i = 0; i < soldOrderLength; i++) {
                        SellingManagerSoldOrderType sellingManagerSoldOrder = sellingManagerSoldOrders[i];
                        String buyerId = sellingManagerSoldOrder.getBuyerID().toString();
                        List<Map<String, Object>> soldGroupList = FastList.newInstance();
                        Map<String, Object> mymap = FastMap.newInstance();
                        mymap.put("group", "");
                        mymap.put("soldorder", sellingManagerSoldOrder);
                        if (h.size() > 0) {
                            Enumeration<String> enums = h.keys();
                            String key = "";
                            while (enums.hasMoreElements()) {
                                key = enums.nextElement();
                                List<Map<String, Object>> tempList = h.get(key);
                                if (key.equals(buyerId)) {
                                    key = buyerId;
                                    tempList.add(mymap);
                                    h.put(buyerId, tempList);
                                }
                            }
                            if (!key.equals(buyerId)) {
                                soldGroupList.clear();
                                soldGroupList.add(mymap);
                                h.put(buyerId, soldGroupList);
                            }
                        } else {
                            soldGroupList.add(mymap);
                            h.put(buyerId, soldGroupList);
                        }
                    }

                    Enumeration<String> enums = h.keys();
                    while (enums.hasMoreElements()) {
                        int groupRunning = 0;
                        String key = enums.nextElement();
                        List<Map<String, Object>> soldGroupList = h.get(key);
                        int maxItems = Integer.parseInt(ebayPref.get("condition2").toString());

                        if (soldGroupList.size() > 1) {
                            for (int j = 0; j < soldGroupList.size(); j++) {
                                Map<String, Object> myMap = soldGroupList.get(j);
                                SellingManagerSoldOrderType soldorder = (SellingManagerSoldOrderType) myMap.get("soldorder");
                                Timestamp createdate = UtilDateTime.toTimestamp(soldorder.getCreationTime().getTime());
                                if (myMap.get("group").toString().length() == 0) {
                                    beginDate = createdate;
                                }
                                beginDate = findStartDate(beginDate, soldGroupList);
                                runCheckAndGroup(groupRunning, beginDate, daysCount, soldGroupList);
                                groupRunning++;
                            }

                            int x = 0;
                            while (x < groupRunning) {
                                OrderType order = new OrderType();
                                order.setCreatingUserRole(TradingRoleCodeType.SELLER);
                                BuyerPaymentMethodCodeType[] buyerPayment = new BuyerPaymentMethodCodeType[1];
                                buyerPayment[0] = BuyerPaymentMethodCodeType.CASH_ON_PICKUP;
                                order.setPaymentMethods(buyerPayment);
                                TransactionArrayType transactionArr = new TransactionArrayType();
                                List<TransactionType> translist = FastList.newInstance();

                                AmountType total = new AmountType();
                                double totalAmt = 0.0;
                                CurrencyCodeType currencyId = null;
                                int totalQty = 0;

                                for (int j = 0; j < soldGroupList.size(); j++) {
                                    Map<String, Object> myMap = soldGroupList.get(j);
                                    if (UtilValidate.isNotEmpty(myMap.get("group"))) {
                                        if (x == Integer.parseInt(myMap.get("group").toString())) {
                                            SellingManagerSoldOrderType sellingManagerSoldOrder = (SellingManagerSoldOrderType) myMap.get("soldorder");
                                            String buyerId = sellingManagerSoldOrder.getBuyerID().toString();
                                            int qty = sellingManagerSoldOrder.getTotalQuantity();
                                            totalQty = totalQty + qty;
                                            if (key.equals(buyerId) && (UtilValidate.isEmpty(sellingManagerSoldOrder.getOrderStatus().getPaidTime()))) {
                                                double totalAmount = 0.0;
                                                if (UtilValidate.isNotEmpty(sellingManagerSoldOrder.getTotalAmount())) {
                                                    totalAmount = sellingManagerSoldOrder.getTotalAmount().getValue();
                                                    currencyId = sellingManagerSoldOrder.getTotalAmount().getCurrencyID();
                                                } else {
                                                    totalAmount = sellingManagerSoldOrder.getSalePrice().getValue();
                                                    currencyId = sellingManagerSoldOrder.getSalePrice().getCurrencyID();
                                                }
                                                //Combine
                                                totalAmt = totalAmt + totalAmount;
                                                SellingManagerSoldTransactionType[] sellingManagerSoldTransactions = sellingManagerSoldOrder.getSellingManagerSoldTransaction();
                                                //set transaction
                                                for (int count = 0; count < sellingManagerSoldTransactions.length; count++) {
                                                    SellingManagerSoldTransactionType sellingManagerSoldTransaction = sellingManagerSoldTransactions[count];
                                                    TransactionType transtype = new TransactionType();
                                                    ItemType itemtype = new ItemType();
                                                    if (UtilValidate.isNotEmpty(sellingManagerSoldTransaction.getItemID())) {
                                                        itemtype.setItemID(sellingManagerSoldTransaction.getItemID());
                                                        transtype.setItem(itemtype);
                                                        transtype.setTransactionID(sellingManagerSoldTransaction.getTransactionID().toString());
                                                        translist.add(transtype);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                                if (totalQty < maxItems) {
                                    total.setValue(totalAmt);
                                    total.setCurrencyID(currencyId);
                                    TransactionType[] transArr = new TransactionType[translist.size()];
                                    for (int counter = 0; counter < translist.size(); counter++) {
                                        transArr[counter] = translist.get(counter);
                                    }
                                    transactionArr.setTransaction(transArr);
                                    if (transactionArr.getTransactionLength() > 1) {
                                        order.setTotal(total);
                                        order.setTransactionArray(transactionArr);
                                        AddOrderCall call = new AddOrderCall(apiContext);
                                        AddOrderRequestType req = new AddOrderRequestType();
                                        AddOrderResponseType resp = null;
                                        req.setOrder(order);
                                        resp = (AddOrderResponseType) call.execute(req);
                                        if (resp != null && "SUCCESS".equals(resp.getAck().toString())) {
                                            String orderId = resp.getOrderID();
                                            Debug.logInfo(":: new order id is = " + orderId, module);
                                        } else {
                                            EbayStoreHelper.createErrorLogMessage(userLogin, dispatcher, productStoreId, resp.getAck().toString(), "Add order : runCombineOrders", resp.getErrors(0).getLongMessage());
                                        }
                                    }
                                }
                                x++;
                            }
                        }
                    }
                }
            }
            result = ServiceUtil.returnSuccess();
        } catch (GenericServiceException e) {
            result = ServiceUtil.returnError(e.getMessage());
        } catch (Exception e) {
            return ServiceUtil.returnError(e.getMessage());
        }
        return result;
    }

    public static Timestamp findStartDate(Timestamp lessStartTimestamp, List<Map<String, Object>> inList) {
        for (Map<String, Object> inMap : inList) {
            SellingManagerSoldOrderType soldorder = (SellingManagerSoldOrderType) inMap.get("soldorder");
            Timestamp createTimestamp = UtilDateTime.toTimestamp(soldorder.getCreationTime().getTime());
            String group = (String) inMap.get("group");
            if (createTimestamp.before(lessStartTimestamp) && group.length() == 0) {
                lessStartTimestamp = createTimestamp;
            }
        }
        return lessStartTimestamp;
    }

    public static void runCheckAndGroup(int groupRunning, Timestamp startTimestamp, long countDays, List<Map<String, Object>> inList) {
        Timestamp endDate = UtilDateTime.getDayEnd(UtilDateTime.toTimestamp(startTimestamp), countDays);
        for (Map<String, Object> inMap : inList) {
            String group = inMap.get("group").toString();
            SellingManagerSoldOrderType soldorder = (SellingManagerSoldOrderType) inMap.get("soldorder");
            if (group.length() == 0) {
                Timestamp createtimestamp = UtilDateTime.toTimestamp(soldorder.getCreationTime().getTime());
                if (((createtimestamp.equals(startTimestamp)) || (createtimestamp.after(startTimestamp))) && (createtimestamp.before(endDate))) {
                    inMap.put("group", "" + groupRunning);
                }
            }
        }
    }

    public static Map<String, Object> autoSendWinningBuyerNotification(DispatchContext dctx, Map<String, Object> context) {
        Map<String, Object> result = FastMap.newInstance();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        String productStoreId = (String) context.get("productStoreId");
        try {
            GenericValue userLogin = delegator.findOne("UserLogin", false, "userLoginId", "system");
            Map<String, Object> resultSold =  dispatcher.runSync("getEbaySoldItems", UtilMisc.toMap("productStoreId", productStoreId, "userLogin", userLogin));
            List<Map<String, Object>> soldItems = UtilGenerics.checkList(resultSold.get("soldItems"));
            if (soldItems.size() != 0) {
                for (int i = 0; i < soldItems.size(); i++) {
                    Map<String, Object> item = soldItems.get(i);
                    Timestamp lastestTime = UtilDateTime.getDayStart(UtilDateTime.nowTimestamp(), 1);
                    Date creationDate = (Date) item.get("creationTime");
                    Timestamp creationTime = UtilDateTime.toTimestamp(creationDate);

                    if (creationTime.equals(lastestTime) && (item.get("listingType").toString().equals("Chinese"))) {
                        Map<String, Object> serviceMap = FastMap.newInstance();
                        serviceMap.put("userLogin", userLogin);
                        serviceMap.put("locale", locale);
                        serviceMap.put("productStoreId", productStoreId);
                        serviceMap.put("itemId", item.get("itemId").toString());
                        Map<String, Object> resultBid =  dispatcher.runSync("getEbayAllBidders", serviceMap);
                        List<Map<String, Object>> allBidders =  UtilGenerics.checkList(resultBid.get("allBidders"));

                        if (allBidders.size() != 0) {
                            // call to send email to bidder
                            for (int j = 0; j < allBidders.size(); j++) {
                                Map<String, Object> bidder = allBidders.get(j);
                                UserType user = (UserType) bidder.get("bidder");
                                String buyerUserId = bidder.get("userId").toString();

                                Map<String, Object> sendMap = FastMap.newInstance();
                                GenericValue productStoreEmail = delegator.findByPrimaryKey("OldProdStoreEmailSetting", UtilMisc.toMap("productStoreId", productStoreId, "emailType", "EBAY_WIN_BUYER_NOTI"));
                                String bodyScreenLocation = productStoreEmail.getString("bodyScreenLocation");
                                sendMap.put("bodyScreenUri", bodyScreenLocation);
                                String subjectString = productStoreEmail.getString("subject");
                                sendMap.put("userLogin", userLogin);
                                sendMap.put("subject", subjectString);
                                sendMap.put("contentType", productStoreEmail.get("contentType"));
                                sendMap.put("sendFrom", productStoreEmail.get("fromAddress"));
                                sendMap.put("sendCc", productStoreEmail.get("ccAddress"));
                                sendMap.put("sendBcc", productStoreEmail.get("bccAddress"));
                                sendMap.put("sendTo", user.getEmail());

                                Map<String, Object> bodyParameters = FastMap.newInstance();
                                bodyParameters.put("buyerUserId", buyerUserId);
                                sendMap.put("bodyParameters", bodyParameters);

                                try {
                                    dispatcher.runAsync("sendMailFromScreen", sendMap);
                                } catch (Exception e) {
                                    Debug.logError(e, module);
                                    return ServiceUtil.returnError(e.getMessage());
                                }
                            }
                        }
                    }
                }
            }
            result = ServiceUtil.returnSuccess();
        } catch (GenericServiceException e) {
            result = ServiceUtil.returnError(e.getMessage());
        } catch (Exception e) {
            return ServiceUtil.returnError(e.getMessage());
        }
        return result;
    }

    public static Map<String, Object> autoSendItemDispatchedNotification(DispatchContext dctx, Map<String, Object> context) {
        Map<String, Object> result = FastMap.newInstance();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        String productStoreId = (String) context.get("productStoreId");

        try {
            GenericValue userLogin = delegator.findOne("UserLogin", false, "userLoginId", "system");
            context.put("userLogin", userLogin);
            Map<String, Object> resultSold =  dispatcher.runSync("getEbaySoldItems", context);
            List<Map<String, Object>> soldItems = UtilGenerics.checkList(resultSold.get("soldItems"));
            if (soldItems.size() != 0) {
                for (int i = 0; i < soldItems.size(); i++) {
                    Map<String, Object> item = soldItems.get(i);
                    String shippedStatus = item.get("shippedStatus").toString();
                    Timestamp lastestTime = UtilDateTime.getDayStart(UtilDateTime.nowTimestamp(), 1);
                    Date shippedTime = (Date) item.get("shippedTime");
                    Timestamp shippedTimestamp = UtilDateTime.toTimestamp(shippedTime);

                    if ("SHIPPED".equals(shippedStatus) && shippedTimestamp.equals(lastestTime)) {
                        String buyerUserId = item.get("buyerUserId").toString();
                        String buyerEmail = item.get("buyerEmail").toString();

                         Map<String, Object> sendMap = FastMap.newInstance();
                         GenericValue productStoreEmail = delegator.findByPrimaryKey("OldProdStoreEmailSetting", UtilMisc.toMap("productStoreId", productStoreId, "emailType", "EBAY_ITEM_DISPATCH"));
                         String bodyScreenLocation = productStoreEmail.getString("bodyScreenLocation");
                         sendMap.put("bodyScreenUri", bodyScreenLocation);
                         String subjectString = productStoreEmail.getString("subject");
                         sendMap.put("userLogin", userLogin);
                         sendMap.put("subject", subjectString);
                         sendMap.put("contentType", productStoreEmail.get("contentType"));
                         sendMap.put("sendFrom", productStoreEmail.get("fromAddress"));
                         sendMap.put("sendCc", productStoreEmail.get("ccAddress"));
                         sendMap.put("sendBcc", productStoreEmail.get("bccAddress"));
                         sendMap.put("sendTo", buyerEmail);

                         Map<String, Object> bodyParameters = FastMap.newInstance();
                         bodyParameters.put("buyerUserId", buyerUserId);
                         sendMap.put("bodyParameters", bodyParameters);

                         try {
                             dispatcher.runAsync("sendMailFromScreen", sendMap);
                         } catch (Exception e) {
                             Debug.logError(e, module);
                             return ServiceUtil.returnError(e.getMessage());
                         }
                        
                    }
                }
            }
            result = ServiceUtil.returnSuccess();
        } catch (GenericServiceException e) {
            result = ServiceUtil.returnError(e.getMessage());
        } catch (Exception e) {
            return ServiceUtil.returnError(e.getMessage());
        }
        return result;
    }

    public static Map<String,Object> autoBlockItemsOutOfStock(DispatchContext dctx, Map<String,Object> context) {
        Locale locale = (Locale) context.get("locale");
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Delegator delegator = dctx.getDelegator();
        Map<String,Object> result = FastMap.newInstance();
        GetSellingManagerInventoryRequestType req = new GetSellingManagerInventoryRequestType();
        GetSellingManagerInventoryResponseType resp =  null;

        if (context.get("productStoreId") != null) {
            GetSellingManagerInventoryCall call = new GetSellingManagerInventoryCall(EbayStoreHelper.getApiContext((String)context.get("productStoreId"), locale, delegator));

            try {
                SellingManagerProductType[] returnedSellingManagerProductType = null;
                resp = (GetSellingManagerInventoryResponseType)call.execute(req);
                if (resp != null && "SUCCESS".equals(resp.getAck().toString())) {
                    returnedSellingManagerProductType  = resp.getSellingManagerProduct();
                    for (int i = 0; i < returnedSellingManagerProductType.length; i++) {
                       SellingManagerProductDetailsType prodDetailType = returnedSellingManagerProductType[i].getSellingManagerProductDetails();
                       int qty = prodDetailType.getQuantityAvailable();

                       if (qty == 0) {
                           SellingManagerTemplateDetailsArrayType sellingTempArr =  returnedSellingManagerProductType[i].getSellingManagerTemplateDetailsArray();
                           SellingManagerTemplateDetailsType[] selllingTempType = null;
                           if (UtilValidate.isNotEmpty(sellingTempArr)) {
                               selllingTempType = sellingTempArr.getSellingManagerTemplateDetails();
                           }

                           if (selllingTempType.length > 0) {
                               for (int j = 0; j < selllingTempType.length; j++) {
                                   Long longTemplete = Long.parseLong(selllingTempType[j].getSaleTemplateID());
                                   DeleteSellingManagerTemplateCall tcall = new DeleteSellingManagerTemplateCall(EbayStoreHelper.getApiContext((String)context.get("productStoreId"), locale, delegator));
                                   DeleteSellingManagerTemplateRequestType treq = new DeleteSellingManagerTemplateRequestType();
                                   DeleteSellingManagerTemplateResponseType tresp =  null;
                                   treq.setSaleTemplateID(longTemplete);

                                   tresp = (DeleteSellingManagerTemplateResponseType) tcall.execute(treq);
                                   if (tresp != null && "SUCCESS".equals(tresp.getAck().toString())) {
                                      result = ServiceUtil.returnSuccess();
                                   } else {
                                       EbayStoreHelper.createErrorLogMessage(userLogin, dctx.getDispatcher(), context.get("productStoreId").toString(), tresp.getAck().toString(), "Delete selling manager template : autoBlockItemsOutOfStock", tresp.getErrors(0).getLongMessage());
                                   }
                               }
                           }
                       }
                    }
                    result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
                } else {
                    EbayStoreHelper.createErrorLogMessage(userLogin, dctx.getDispatcher(), context.get("productStoreId").toString(), resp.getAck().toString(), "Get selling manager inventory : autoBlockItemsOutOfStock", resp.getErrors(0).getLongMessage());
                }
                result = ServiceUtil.returnSuccess();
            } catch (ApiException e) {
                e.printStackTrace();
            } catch (SdkSoapException e) {
                e.printStackTrace();
            } catch (SdkException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    public static Map<String, Object> autoRelistingItems(DispatchContext dctx, Map<String, ? extends Object> context) {
        Map<String, Object> itemObject = FastMap.newInstance();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        try {
            GenericValue userLogin = delegator.findOne("UserLogin", false, "userLoginId", "system");
            EntityCondition expression1 = EntityCondition.makeCondition("autoRelisting", EntityOperator.EQUALS, "Y");
            EntityCondition expression2 = EntityCondition.makeCondition("endDateTime", EntityOperator.LESS_THAN, UtilDateTime.nowTimestamp());
            EntityCondition expression3 = EntityCondition.makeCondition("itemId", EntityOperator.NOT_EQUAL, null);
            List<EntityCondition> expressions = FastList.newInstance();
            expressions.add(expression1);
            expressions.add(expression2);
            expressions.add(expression3);
            EntityCondition cond = EntityCondition.makeCondition(expressions, EntityOperator.AND);
            List<GenericValue> ebayProductListings = delegator.findList("EbayProductListing", cond , null, null, null, false);
            for (int index = 0; index < ebayProductListings.size(); index++) {
                Map<String, Object> inMap = FastMap.newInstance();
                AddItemCall addItemCall = new AddItemCall(EbayStoreHelper.getApiContext((String)context.get("productStoreId"), locale, delegator));
                GenericValue ebayProductListing = ebayProductListings.get(index);
                ItemType item = EbayStoreHelper.prepareAddItem(delegator, ebayProductListing);
                addItemCall.setItem(item);
                itemObject.put("addItemCall", addItemCall);
                itemObject.put("productListingId", ebayProductListing.getString("productListingId"));
                inMap.put("itemObject", itemObject);
                inMap.put("userLogin", userLogin);
                Map<String, Object>result = dispatcher.runSync("exportProductEachItem", inMap);
                String success = (String) result.get("responseMessage");
                if ("success".equals(success)) {
                    String duration = item.getListingDuration();
                    if (duration.length() > 4) {
                        Timestamp startDateTime = UtilDateTime.nowTimestamp();
                        int durationInt = Integer.parseInt(duration.replace("DAYS_", ""));
                        Timestamp endDateTime = UtilDateTime.addDaysToTimestamp(startDateTime, durationInt);
                        ebayProductListing.set("startDateTime", startDateTime);
                        ebayProductListing.set("endDateTime", endDateTime);
                        ebayProductListing.store();
                    }
                }
            }
        } catch (Exception e) {
            return ServiceUtil.returnError(e.getMessage());
        }
        return ServiceUtil.returnSuccess();
    }
    public static Map<String, Object> autoBestOffer(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        try {
            String productStoreId = (String) context.get("productStoreId");
            GenericValue ebayProductStorePref = delegator.findByPrimaryKey("EbayProductStorePref", UtilMisc.toMap("productStoreId", productStoreId, "autoPrefEnumId", "EBAY_AUTO_BEST_OFFER"));
            String parentPrefCondId = ebayProductStorePref.getString("parentPrefCondId");
            List<GenericValue> ebayProductStorePrefCond = delegator.findByAnd("EbayProductStorePrefCond", UtilMisc.toMap("parentPrefCondId", parentPrefCondId));
            //Parameters
            String priceType = ebayProductStorePrefCond.get(0).getString("acceptanceCondition");
            String acceptBestOfferValue = ebayProductStorePrefCond.get(1).getString("acceptanceCondition");
            String rejectOffer = ebayProductStorePrefCond.get(2).getString("acceptanceCondition");
            String ignoreOfferMessage = ebayProductStorePrefCond.get(3).getString("acceptanceCondition");
            String rejectGreaterEnable = ebayProductStorePrefCond.get(4).getString("acceptanceCondition");
            String greaterValue = ebayProductStorePrefCond.get(5).getString("acceptanceCondition");
            String lessValue = ebayProductStorePrefCond.get(6).getString("acceptanceCondition");
            String rejectGreaterMsg = ebayProductStorePrefCond.get(7).getString("acceptanceCondition");
            String rejectLessEnable = ebayProductStorePrefCond.get(8).getString("acceptanceCondition");
            String lessThanValue = ebayProductStorePrefCond.get(9).getString("acceptanceCondition");
            String rejectLessMsg = ebayProductStorePrefCond.get(10).getString("acceptanceCondition");
            //case parameter to double type
            BigDecimal acceptPercentValue = new BigDecimal(acceptBestOfferValue);
            BigDecimal greaterPercentValue = new BigDecimal(greaterValue);
            BigDecimal lessThanPercentValue = new BigDecimal(lessValue);
            BigDecimal rejectPercentValue = new BigDecimal(lessThanValue);

            ApiContext apiContext = EbayStoreHelper.getApiContext(productStoreId, locale, delegator);
            //GetMysbaySellingCall for get total page
            GetMyeBaySellingCall getTotalPage = new GetMyeBaySellingCall(apiContext);
            ItemListCustomizationType itemListType = new ItemListCustomizationType();
            itemListType.setInclude(Boolean.TRUE);
            itemListType.setSort(ItemSortTypeCodeType.ITEM_ID_DESCENDING);
            itemListType.setListingType(ListingTypeCodeType.FIXED_PRICE_ITEM);
            DetailLevelCodeType[] detailLevels = new DetailLevelCodeType[] {
                DetailLevelCodeType.RETURN_ALL,
                DetailLevelCodeType.ITEM_RETURN_ATTRIBUTES,
                DetailLevelCodeType.ITEM_RETURN_DESCRIPTION
            };
            getTotalPage.setDetailLevel(detailLevels);
            getTotalPage.setActiveList(itemListType);
            getTotalPage.getMyeBaySelling();
            int totalPage = getTotalPage.getReturnedActiveList().getPaginationResult().getTotalNumberOfPages();
            for (int t = 1; t <= totalPage; t++) {
                //GetMyebaySellingCall for get item that is sold on store
                GetMyeBaySellingCall ebaySelling = new GetMyeBaySellingCall(apiContext);
                //Set type of item
                ItemListCustomizationType itemList = new ItemListCustomizationType();
                itemList.setInclude(Boolean.TRUE);
                itemListType.setSort(ItemSortTypeCodeType.ITEM_ID_DESCENDING);
                itemListType.setListingType(ListingTypeCodeType.FIXED_PRICE_ITEM);

                PaginationType page = new PaginationType();
                page.setPageNumber(t);
                itemList.setPagination(page);
                itemList.setListingType(ListingTypeCodeType.FIXED_PRICE_ITEM);

                DetailLevelCodeType[] detailLevel = new DetailLevelCodeType[] {
                        DetailLevelCodeType.RETURN_ALL,
                        DetailLevelCodeType.ITEM_RETURN_ATTRIBUTES,
                        DetailLevelCodeType.ITEM_RETURN_DESCRIPTION,
                        DetailLevelCodeType.RETURN_HEADERS,
                        DetailLevelCodeType.RETURN_MESSAGES
                };
                ebaySelling.setDetailLevel(detailLevel);
                ebaySelling.setActiveList(itemList);
                ebaySelling.getMyeBaySelling();
                PaginatedItemArrayType itemListCustomizationType = ebaySelling.getReturnedActiveList();
                ItemArrayType itemArrayType = itemListCustomizationType.getItemArray();
                int itemArrayTypeSize = itemArrayType.getItemLength();

                //Loop for get item
                for (int itemCount = 0; itemCount < itemArrayTypeSize; itemCount++) {
                    ItemType item = itemArrayType.getItem(itemCount);
                    String itemID = item.getItemID();
                    Double buyItNowPrice = item.getBuyItNowPrice().getValue();
                    GetItemCall getItem = new GetItemCall(apiContext);
                    getItem.setDetailLevel(detailLevel);
                    getItem.getItem(itemID);
                    String SKUItem = getItem.getSKU();
                    ItemType itemBestOffer = getItem.getReturnedItem();
                    BestOfferDetailsType bestOfferDetailsType = itemBestOffer.getBestOfferDetails();
                    int inventoryQuantityItem = item.getQuantityAvailable();  //Quantity of the item
                    int bestOfferCount = itemBestOffer.getBestOfferDetails().getBestOfferCount();
                    Boolean bestOfferIsEnabled = itemBestOffer.getBestOfferDetails().isBestOfferEnabled();
                    //Check value of Best offer Detail not null
                    if ((bestOfferDetailsType != null) && (bestOfferCount > 0) && bestOfferIsEnabled.equals(true)) {
                        //Get base price from kindOfPrice parameter
                        Double doBasePrice = null;
                        if (priceType.equals("BUY_IT_NOW_PRICE")) {
                            doBasePrice = buyItNowPrice;
                        } else if (priceType.equals("START_PRICE")) {
                            doBasePrice = itemBestOffer.getStartPrice().getValue();
                        } else if (priceType.equals("RESERVE_PRICE")) {
                            doBasePrice = itemBestOffer.getReservePrice().getValue();
                        } else if (priceType.equals("RETAIL_PRICE")) {
                            //ignore
                        } else if (priceType.equals("SELLER_COST")) {
                            List<GenericValue> supplierProduct = delegator.findByAnd("SupplierProduct", UtilMisc.toMap("productId", SKUItem), UtilMisc.toList("availableFromDate DESC"));
                            String lastPrice = supplierProduct.get(0).getString("lastPrice");
                            doBasePrice = Double.parseDouble(lastPrice);
                        } else if (priceType.equals("SECOND_CHANCE_PRICE")) {
                            VerifyAddSecondChanceItemCall verifyAddSecondChanceItemCall = new VerifyAddSecondChanceItemCall(apiContext);
                            doBasePrice = verifyAddSecondChanceItemCall.getBuyItNowPrice().getValue();
                        } else if (priceType.equals("STORE_PRICE")) {
                            //ignore
                        }
                        BigDecimal basePrice = new BigDecimal(doBasePrice);
                        BigDecimal percent = new BigDecimal(100);
                        //Calculate price with base price and percent from parameter
                        BigDecimal acceptPrice = (basePrice.multiply(acceptPercentValue)).divide(percent);
                        BigDecimal greaterPrice = (basePrice.multiply(greaterPercentValue)).divide(percent);
                        BigDecimal lessThanPrice = (basePrice.multiply(lessThanPercentValue)).divide(percent);
                        BigDecimal rejectPrice = (basePrice.multiply(rejectPercentValue)).divide(percent);

                        //GetBestOfferCall for get best offer detail
                        GetBestOffersCall getBestOfferCall = new GetBestOffersCall(apiContext);
                        getBestOfferCall.setItemID(itemID);
                        getBestOfferCall.setDetailLevel(detailLevel);
                        getBestOfferCall.setBestOfferStatus(BestOfferStatusCodeType.ALL);
                        getBestOfferCall.getBestOffers();
                        BestOfferType[] bestOffers = getBestOfferCall.getReturnedBestOffers();
                        List<String> acceptBestOfferIndexId = FastList.newInstance();
                        SortedMap<String, Object> acceptBestOfferIDs = new TreeMap<String, Object>();
                        //Loop for get data best offer from buyer
                        RespondToBestOfferCall respondToBestOfferCall = new RespondToBestOfferCall(apiContext);
                        respondToBestOfferCall.setItemID(itemID);
                        for (int offerCount = 0; offerCount < bestOffers.length; offerCount++) {
                            BestOfferType bestOfferType = bestOffers[offerCount];
                            BestOfferStatusCodeType bestOfferStatusCodeType = bestOfferType.getStatus();
                            //Check status of best offer
                            if (bestOfferStatusCodeType == BestOfferStatusCodeType.PENDING) {
                                String bestOfferID = bestOfferType.getBestOfferID();
                                UserType buyer = bestOfferType.getBuyer();
                                String buyerUserID = buyer.getUserID();
                                AmountType price = bestOfferType.getPrice();
                                String offerPrice = new Double(price.getValue()).toString();
                                Double doCerrentPrice = Double.parseDouble(offerPrice);
                                int offerQuantity = bestOfferType.getQuantity();
                                String[] bestOfferIDs = { bestOfferID };
                                respondToBestOfferCall.setBestOfferIDs(bestOfferIDs);

                                if (rejectOffer.equals("Y")) {
                                    if (offerQuantity > inventoryQuantityItem) {
                                        respondToBestOfferCall.setSellerResponse("Your order is more than inventory item's Buy-It-Now price.");
                                        respondToBestOfferCall.setBestOfferAction(BestOfferActionCodeType.DECLINE);
                                        respondToBestOfferCall.respondToBestOffer();
                                        continue;
                                    }
                                }

                                String buyerMessage = bestOfferType.getBuyerMessage();
                                if (ignoreOfferMessage.equals("Y") && UtilValidate.isNotEmpty(buyerMessage)) {
                                    GenericValue userOfferCheck = delegator.findByPrimaryKey("EbayUserBestOffer", UtilMisc.toMap("itemId", itemID, "userId", buyerUserID));
                                    if (UtilValidate.isEmpty(userOfferCheck)) {
                                        GenericValue ebayUserBestOffer = delegator.makeValue("EbayUserBestOffer");
                                        ebayUserBestOffer.put("productStoreId", productStoreId);
                                        ebayUserBestOffer.put("itemId", itemID);
                                        ebayUserBestOffer.put("userId", buyerUserID);
                                        ebayUserBestOffer.put("bestOfferId", bestOfferID);
                                        ebayUserBestOffer.put("contactStatus", "NOT_CONTACT");
                                        ebayUserBestOffer.create();
                                    }
                                    continue;
                                }
                                BigDecimal cerrentPrice = new BigDecimal(doCerrentPrice);
                                if (cerrentPrice.compareTo(acceptPrice) >= 0) {
                                    acceptBestOfferIndexId.add(bestOfferID);
                                    String Quantity = String.valueOf(offerQuantity);
                                    acceptBestOfferIDs.put(bestOfferID, Quantity);
                                } else if ((cerrentPrice.compareTo(greaterPrice) >= 0) && (cerrentPrice.compareTo(lessThanPrice) <= 0 ) && rejectGreaterEnable.equals("Y")) {
                                    respondToBestOfferCall.setBestOfferAction(BestOfferActionCodeType.DECLINE);
                                    respondToBestOfferCall.setSellerResponse(rejectGreaterMsg);
                                    respondToBestOfferCall.respondToBestOffer();
                                } else if ((cerrentPrice.compareTo(rejectPrice) <= 0 && rejectLessEnable.equals("Y"))) {
                                    respondToBestOfferCall.setBestOfferAction(BestOfferActionCodeType.DECLINE);
                                    respondToBestOfferCall.setSellerResponse(rejectLessMsg);
                                    respondToBestOfferCall.respondToBestOffer();
                                } else {
                                    respondToBestOfferCall.setBestOfferAction(BestOfferActionCodeType.DECLINE);
                                    respondToBestOfferCall.respondToBestOffer();
                                }
                            }
                        }

                        if (acceptBestOfferIndexId.size() > 0) {
                            int quantityAvailable = inventoryQuantityItem;
                            Collections.sort(acceptBestOfferIndexId);
                            RespondToBestOfferCall respondAcceptBestOfferCall = new RespondToBestOfferCall(apiContext);
                            respondAcceptBestOfferCall.setItemID(itemID);
                            for (String bestOfferIdIndex : acceptBestOfferIndexId) {
                                if (quantityAvailable <= 0) break;
                                Integer offerQuantity = Integer.parseInt(acceptBestOfferIDs.get(bestOfferIdIndex).toString());
                                String[] bestOfferID = { bestOfferIdIndex };
                                respondAcceptBestOfferCall.setBestOfferIDs(bestOfferID);
                                //respondAcceptBestOfferCall.setBestOfferIDs(bestOfferID);
                                if (offerQuantity <= quantityAvailable) {
                                    respondAcceptBestOfferCall.setBestOfferAction(BestOfferActionCodeType.ACCEPT);
                                    quantityAvailable = quantityAvailable - offerQuantity;
                                } else {
                                    respondAcceptBestOfferCall.setBestOfferAction(BestOfferActionCodeType.DECLINE);
                                }
                                respondAcceptBestOfferCall.respondToBestOffer();
                            }
                        }
                    }
                }
            }
        } catch (ApiException e){
            return ServiceUtil.returnError(e.getMessage());
        }catch(Exception e){
            return ServiceUtil.returnError(e.getMessage());
        }
        return ServiceUtil.returnSuccess();
    }
}
