/*
 * 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.entity.util.EntityQuery;
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 = EntityQuery.use(delegator).from("EbayProductStorePref").where("productStoreId", productStoreId, "autoPrefEnumId", "EBAY_AUTO_PIT_FB").queryOne();
            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 = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
            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 = EntityQuery.use(delegator).from("EbayProductStorePref").where("productStoreId", productStoreId, "autoPrefEnumId", "EBAY_AUTO_PIT_FB").queryOne();
            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 = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
        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 = EntityQuery.use(delegator).from("EbayProductStorePref").where("productStoreId", productStoreId, "autoPrefEnumId", "EBAY_AUTO_FB_RMD").queryOne();
            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 = EntityQuery.use(delegator).from("ProductStoreEmailSetting").where("productStoreId", productStoreId, "emailType", "EBAY_FEEBACK_REMIN").queryOne();
                            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 = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
            Map<String, Object> serviceMap = FastMap.newInstance();
            serviceMap.put("userLogin", userLogin);
            //ProductStore
            List<GenericValue> productStores = EntityQuery.use(delegator).from("EbayProductStorePref").where("autoPrefJobId", jobId).queryList();
            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 = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", eBayUserLoginId).queryOne();
                    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 = EntityQuery.use(delegator).from("Product").where("productId", soldItemMap.get("itemId")).queryOne();
                                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 = EntityQuery.use(delegator).from("ProductRole").where("partyId", partyId, "productId", soldItemMap.get("itemId"), "roleTypeId", "VENDOR").queryList();
                                    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 = EntityQuery.use(delegator).from("ProductRole").where("partyId", partyId, "roleTypeId", "VENDOR").queryList();
                    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);
                    List<GenericValue> itemsToRelist = EntityQuery.use(delegator).from("Product").where(andExpr).queryList();
                    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 = EntityQuery.use(delegator).from("Product").where("productId", product.getString("productId")).queryOne();
                            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 = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
            List<GenericValue> productStores = EntityQuery.use(delegator).from("EbayProductStorePref").where("autoPrefJobId", jobId).queryList();
            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 = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
            List<GenericValue> productStores = EntityQuery.use(delegator).from("EbayProductStorePref").where("autoPrefJobId", jobId).queryList();
            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 = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();

        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 = EntityQuery.use(delegator).from("EbayProductStorePref").where("productStoreId", productStoreId, "autoPrefEnumId", "EBAY_AUTO_FB_RMD").queryOne();
            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 = EntityQuery.use(delegator).from("ProductStoreEmailSetting").where("productStoreId", productStoreId, "emailType", "EBAY_PAY_RECIEVED").queryOne();
                            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 = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
            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 = EntityQuery.use(delegator).from("EbayProductStorePref").where("productStoreId", productStoreId, "autoPrefEnumId", "ENA_COMB_ORD").queryOne();
                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 = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
            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 = EntityQuery.use(delegator).from("ProductStoreEmailSetting").where("productStoreId", productStoreId, "emailType", "EBAY_WIN_BUYER_NOTI").queryOne();
                                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 = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
            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 = EntityQuery.use(delegator).from("ProductStoreEmailSetting").where("productStoreId", productStoreId, "emailType", "EBAY_ITEM_DISPATCH").queryOne();
                         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 = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
            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 = EntityQuery.use(delegator).from("EbayProductListing").where(expressions).queryList();
            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 = EntityQuery.use(delegator).from("EbayProductStorePref").where("productStoreId", productStoreId, "autoPrefEnumId", "EBAY_AUTO_BEST_OFFER").queryOne();
            String parentPrefCondId = ebayProductStorePref.getString("parentPrefCondId");
            List<GenericValue> ebayProductStorePrefCond = EntityQuery.use(delegator).from("EbayProductStorePrefCond").where("parentPrefCondId", parentPrefCondId).queryList();
            //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 = EntityQuery.use(delegator).from("SupplierProduct").where("productId", SKUItem).orderBy("availableFromDate DESC").queryList();
                            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 = EntityQuery.use(delegator).from("EbayUserBestOffer").where("itemId", itemID, "userId", buyerUserID).queryOne();
                                    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();
    }
}
