/*******************************************************************************
 * 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.accounting.thirdparty.paypal;

import java.io.IOException;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.lang.ref.WeakReference;
import java.math.BigDecimal;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.WeakHashMap;

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

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

import org.apache.commons.lang.StringUtils;
import org.ofbiz.accounting.payment.PaymentGatewayServices;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.GeneralException;
import org.ofbiz.base.util.StringUtil;
import org.ofbiz.base.util.UtilDateTime;
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.EntityComparisonOperator;
import org.ofbiz.entity.condition.EntityCondition;
import org.ofbiz.entity.condition.EntityFunction;
import org.ofbiz.entity.transaction.GenericTransactionException;
import org.ofbiz.entity.transaction.TransactionUtil;
import org.ofbiz.entity.util.EntityUtil;
import org.ofbiz.order.order.OrderReadHelper;
import org.ofbiz.order.shoppingcart.CartItemModifyException;
import org.ofbiz.order.shoppingcart.CheckOutHelper;
import org.ofbiz.order.shoppingcart.ShoppingCart;
import org.ofbiz.order.shoppingcart.ShoppingCartItem;
import org.ofbiz.order.shoppingcart.ShoppingCart.CartShipInfo;
import org.ofbiz.order.shoppingcart.shipping.ShippingEstimateWrapper;
import org.ofbiz.order.shoppingcart.shipping.ShippingEvents;
import org.ofbiz.product.store.ProductStoreWorker;
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.paypal.sdk.core.nvp.NVPDecoder;
import com.paypal.sdk.core.nvp.NVPEncoder;
import com.paypal.sdk.exceptions.PayPalException;
import com.paypal.sdk.profiles.APIProfile;
import com.paypal.sdk.profiles.ProfileFactory;
import com.paypal.sdk.services.NVPCallerServices;

/**
 * PayPalServices for NVP API communication
 */
public class PayPalServices {

    public static final String module = PayPalServices.class.getName();
    public final static String resource = "AccountingErrorUiLabels";
    
    // Used to maintain a weak reference to the ShoppingCart for customers who have gone to PayPal to checkout
    // so that we can quickly grab the cart, perform shipment estimates and send the info back to PayPal.
    // The weak key is a simple wrapper for the checkout token String and is stored as a cart attribute. The value
    // is a weak reference to the ShoppingCart itself.  Entries will be removed as carts are removed from the
    // session (i.e. on cart clear or successful checkout) or when the session is destroyed
    private static Map<TokenWrapper, WeakReference<ShoppingCart>> tokenCartMap = new WeakHashMap<TokenWrapper, WeakReference<ShoppingCart>>();

    public static Map<String, Object> setExpressCheckout(DispatchContext dctx, Map<String, ? extends Object> context) {
        ShoppingCart cart = (ShoppingCart) context.get("cart");
        Locale locale = cart.getLocale();
        if (cart == null || cart.items().size() <= 0) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPayPalShoppingCartIsEmpty", locale));
        }

        GenericValue payPalConfig = getPaymentMethodGatewayPayPal(dctx, context, null);
        if (payPalConfig == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPayPalPaymentGatewayConfigCannotFind", locale));
        }


        NVPEncoder encoder = new NVPEncoder();

        // Set Express Checkout Request Parameters
        encoder.add("METHOD", "SetExpressCheckout");
        String token = (String) cart.getAttribute("payPalCheckoutToken");
        if (UtilValidate.isNotEmpty(token)) {
            encoder.add("TOKEN", token);
        }
        encoder.add("RETURNURL", payPalConfig.getString("returnUrl"));
        encoder.add("CANCELURL", payPalConfig.getString("cancelReturnUrl"));
        if (!cart.shippingApplies()) {
            encoder.add("NOSHIPPING", "1");
        } else {
            encoder.add("CALLBACK", payPalConfig.getString("shippingCallbackUrl"));
            encoder.add("CALLBACKTIMEOUT", "6");
            // Default to no
            String reqConfirmShipping = "Y".equals(payPalConfig.getString("requireConfirmedShipping")) ? "1" : "0";
            encoder.add("REQCONFIRMSHIPPING", reqConfirmShipping);
            // Default shipment method
            encoder.add("L_SHIPPINGOPTIONISDEFAULT0", "true");
            encoder.add("L_SHIPPINGOPTIONNAME0", "Calculated Offline");
            encoder.add("L_SHIPPINGOPTIONAMOUNT0", "0.00");
        }
        encoder.add("ALLOWNOTE", "1");
        encoder.add("INSURANCEOPTIONOFFERED", "false");
        if (UtilValidate.isNotEmpty(payPalConfig.getString("imageUrl")));
        encoder.add("PAYMENTACTION", "Order");

        // Cart information
        try {
            addCartDetails(encoder, cart);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPayPalErrorDuringRetrievingCartDetails", locale));
        }

        NVPDecoder decoder;
        try {
            decoder = sendNVPRequest(payPalConfig, encoder);
        } catch (PayPalException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

        Map<String, String> errorMessages = getErrorMessageMap(decoder);
        if (UtilValidate.isNotEmpty(errorMessages)) {
            if (errorMessages.containsKey("10411")) {
                // Token has expired, get a new one
                cart.setAttribute("payPalCheckoutToken", null);
                return PayPalServices.setExpressCheckout(dctx, context);
            }
            return ServiceUtil.returnError(UtilMisc.toList(errorMessages.values()));
        }

        token = decoder.get("TOKEN");
        cart.setAttribute("payPalCheckoutToken", token);
        TokenWrapper tokenWrapper = new TokenWrapper(token);
        cart.setAttribute("payPalCheckoutTokenObj", tokenWrapper);
        PayPalServices.tokenCartMap.put(tokenWrapper, new WeakReference<ShoppingCart>(cart));
        return ServiceUtil.returnSuccess();
    }

    public static Map<String, Object> payPalCheckoutUpdate(DispatchContext dctx, Map<String, Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        HttpServletRequest request = (HttpServletRequest) context.get("request");
        HttpServletResponse response = (HttpServletResponse) context.get("response");

        Map<String, Object> paramMap = UtilHttp.getParameterMap(request);

        String token = (String)paramMap.get("TOKEN");
        WeakReference<ShoppingCart> weakCart = tokenCartMap.get(new TokenWrapper(token));
        ShoppingCart cart = null;
        if (weakCart != null) {
            cart = weakCart.get();
        }
        if (cart == null) {
            Debug.logError("Could locate the ShoppingCart for token " + token, module);
            return ServiceUtil.returnSuccess();
        }
        // Since most if not all of the shipping estimate codes requires a persisted contactMechId we'll create one and
        // then delete once we're done, now is not the time to worry about updating everything
        String contactMechId = null;
        Map<String, Object> inMap = FastMap.newInstance();
        inMap.put("address1", paramMap.get("SHIPTOSTREET"));
        inMap.put("address2", paramMap.get("SHIPTOSTREET2"));
        inMap.put("city", paramMap.get("SHIPTOCITY"));
        String countryGeoCode = (String) paramMap.get("SHIPTOCOUNTRY");
        String countryGeoId = PayPalServices.getCountryGeoIdFromGeoCode(countryGeoCode, delegator);
        if (countryGeoId == null) {
            return ServiceUtil.returnSuccess();
        }
        inMap.put("countryGeoId", countryGeoId);
        inMap.put("stateProvinceGeoId", parseStateProvinceGeoId((String)paramMap.get("SHIPTOSTATE"), countryGeoId, delegator));
        inMap.put("postalCode", paramMap.get("SHIPTOZIP"));

        try {
            GenericValue userLogin = delegator.findOne("UserLogin", true, UtilMisc.toMap("userLoginId", "system"));
            inMap.put("userLogin", userLogin);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }
        boolean beganTransaction = false;
        Transaction parentTransaction = null;
        try {
            parentTransaction = TransactionUtil.suspend();
            beganTransaction = TransactionUtil.begin();
        } catch (GenericTransactionException e1) {
            Debug.logError(e1, module);
        }
        try {
            Map<String, Object> outMap = dispatcher.runSync("createPostalAddress", inMap);
            contactMechId = (String) outMap.get("contactMechId");
        } catch (GenericServiceException e) {
            Debug.logError(e.getMessage(), module);
            return ServiceUtil.returnSuccess();
        }
        try {
            TransactionUtil.commit(beganTransaction);
            if (parentTransaction != null) TransactionUtil.resume(parentTransaction);
        } catch (GenericTransactionException e) {
            Debug.logError(e, module);
        }
        // clone the cart so we can modify it temporarily
        CheckOutHelper coh = new CheckOutHelper(dispatcher, delegator, cart);
        String oldShipAddress = cart.getShippingContactMechId();
        coh.setCheckOutShippingAddress(contactMechId);
        ShippingEstimateWrapper estWrapper = new ShippingEstimateWrapper(dispatcher, cart, 0);
        int line = 0;
        NVPEncoder encoder = new NVPEncoder();
        encoder.add("METHOD", "CallbackResponse");

        for (GenericValue shipMethod : estWrapper.getShippingMethods()) {
            BigDecimal estimate = estWrapper.getShippingEstimate(shipMethod);
            //Check that we have a valid estimate (allowing zero value estimates for now)
            if (estimate == null || estimate.compareTo(BigDecimal.ZERO) < 0) {
                continue;
            }
            cart.setShipmentMethodTypeId(shipMethod.getString("shipmentMethodTypeId"));
            cart.setCarrierPartyId(shipMethod.getString("partyId"));
            try {
                coh.calcAndAddTax();
            } catch (GeneralException e) {
                Debug.logError(e, module);
                continue;
            }
            String estimateLabel = shipMethod.getString("partyId") + " - " + shipMethod.getString("description");
            encoder.add("L_SHIPINGPOPTIONLABEL" + line, estimateLabel);
            encoder.add("L_SHIPPINGOPTIONAMOUNT" + line, estimate.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
            // Just make this first one default for now
            encoder.add("L_SHIPPINGOPTIONISDEFAULT" + line, line == 0 ? "true" : "false");
            encoder.add("L_TAXAMT" + line, cart.getTotalSalesTax().setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
            line++;
        }
        String responseMsg = null;
        try {
            responseMsg = encoder.encode();
        } catch (PayPalException e) {
            Debug.logError(e, module);
        }
        if (responseMsg != null) {
            try {
                response.setContentLength(responseMsg.getBytes("UTF-8").length);
            } catch (UnsupportedEncodingException e) {
                Debug.logError(e, module);
            }

            try {
                Writer writer = response.getWriter();
                writer.write(responseMsg);
                writer.close();
            } catch (IOException e) {
                Debug.logError(e, module);
            }
        }

        // Remove the temporary ship address
        try {
            GenericValue postalAddress = delegator.findOne("PostalAddress", false, UtilMisc.toMap("contactMechId", contactMechId));
            postalAddress.remove();
            GenericValue contactMech = delegator.findOne("ContactMech", false, UtilMisc.toMap("contactMechId", contactMechId));
            contactMech.remove();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }
        coh.setCheckOutShippingAddress(oldShipAddress);
        return ServiceUtil.returnSuccess();
    }

    private static Map<String, String> getErrorMessageMap(NVPDecoder decoder) {
        String ack = decoder.get("ACK");
        Map<String, String> result = null;
        if (!"Success".equals(ack)) {
            result = FastMap.newInstance();
            int i = 0;
            while (UtilValidate.isNotEmpty(decoder.get("L_ERRORCODE" + i))) {
                String errorCode = decoder.get("L_ERRORCODE" + i);
                String longMsg = decoder.get("L_LONGMESSAGE" + i);
                result.put(errorCode, "PayPal Response Error: [" + errorCode + "]" + longMsg);
                i++;
            }
        }
        return result;
    }

    private static void addCartDetails(NVPEncoder encoder, ShoppingCart cart) throws GenericEntityException {
        encoder.add("CURRENCYCODE", cart.getCurrency());
        int line = 0;
        for (ShoppingCartItem item : cart.items()) {
            encoder.add("L_NUMBER" + line, item.getProductId());
            encoder.add("L_NAME" + line, item.getName());
            encoder.add("L_AMT" + line, item.getBasePrice().setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
            encoder.add("L_QTY" + line, item.getQuantity().toBigInteger().toString());
            line++;
            BigDecimal otherAdjustments = item.getOtherAdjustments();
            if (otherAdjustments.compareTo(BigDecimal.ZERO) != 0) {
                encoder.add("L_NUMBER" + line, item.getProductId());
                encoder.add("L_NAME" + line, item.getName() + " Adjustments");
                encoder.add("L_AMT" + line, otherAdjustments.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
                encoder.add("L_QTY" + line, "1");
                line++;
            }
        }
        BigDecimal otherAdjustments = cart.getOrderOtherAdjustmentTotal();
        if (otherAdjustments.compareTo(BigDecimal.ZERO) != 0) {
            encoder.add("L_NUMBER" + line, "N/A");
            encoder.add("L_NAME" + line, "Order Adjustments");
            encoder.add("L_AMT" + line, otherAdjustments.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
            encoder.add("L_QTY" + line, "1");
            line++;
        }
        encoder.add("ITEMAMT", cart.getSubTotal().add(otherAdjustments).setScale(2).toPlainString());
        encoder.add("SHIPPINGAMT", "0.00");
        encoder.add("TAXAMT", "0.00");
        encoder.add("AMT", cart.getSubTotal().add(otherAdjustments).setScale(2).toPlainString());
        //NOTE: The docs say this is optional but then won't work without it
        encoder.add("MAXAMT", cart.getSubTotal().add(otherAdjustments).setScale(2).toPlainString());
    }

    public static Map<String, Object> getExpressCheckout(DispatchContext dctx, Map<String, Object> context) {
        Locale locale = (Locale) context.get("locale");
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();

        ShoppingCart cart = (ShoppingCart) context.get("cart");
        GenericValue payPalConfig = getPaymentMethodGatewayPayPal(dctx, context, null);
        if (payPalConfig == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPayPalPaymentGatewayConfigCannotFind", locale));
        }

        NVPEncoder encoder = new NVPEncoder();
        encoder.add("METHOD", "GetExpressCheckoutDetails");
        String token = (String) cart.getAttribute("payPalCheckoutToken");
        if (UtilValidate.isNotEmpty(token)) {
            encoder.add("TOKEN", token);
        } else {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPayPalTokenNotFound", locale));
        }

        NVPDecoder decoder;
        try {
            decoder = sendNVPRequest(payPalConfig, encoder);
        } catch (PayPalException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

        if (UtilValidate.isNotEmpty(decoder.get("NOTE"))) {
            cart.addOrderNote(decoder.get("NOTE"));
        }

        if (cart.getUserLogin() == null) {
            try {
                GenericValue userLogin = delegator.findOne("UserLogin", false, "userLoginId", "anonymous");
                try {
                    cart.setUserLogin(userLogin, dispatcher);
                } catch (CartItemModifyException e) {
                    Debug.logError(e, module);
                    return ServiceUtil.returnError(e.getMessage());
                }
            } catch (GenericEntityException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(e.getMessage());
            }
        }
        boolean anon = "anonymous".equals(cart.getUserLogin().getString("userLoginId"));
        // Even if anon, a party could already have been created
        String partyId = cart.getOrderPartyId();
        if (partyId == null && anon) {
            // Check nothing has been set on the anon userLogin either
            partyId = cart.getUserLogin() != null ? cart.getUserLogin().getString("partyId") : null;
            cart.setOrderPartyId(partyId);
        }
        if (partyId != null) {
            GenericValue party = null;
            try {
                party = delegator.findOne("Party", false, "partyId", partyId);
            } catch (GenericEntityException e) {
                Debug.logError(e, module);
            }
            if (party == null) {
                partyId = null;
            }
        }

        Map<String, Object> inMap = FastMap.newInstance();
        Map<String, Object> outMap = null;
        // Create the person if necessary
        boolean newParty = false;
        if (partyId == null) {
            newParty = true;
            inMap.put("userLogin", cart.getUserLogin());
            inMap.put("personalTitle", decoder.get("SALUTATION"));
            inMap.put("firstName", decoder.get("FIRSTNAME"));
            inMap.put("middleName", decoder.get("MIDDLENAME"));
            inMap.put("lastName", decoder.get("LASTNAME"));
            inMap.put("suffix", decoder.get("SUFFIX"));
            try {
                outMap = dispatcher.runSync("createPerson", inMap);
                partyId = (String) outMap.get("partyId");
                cart.setOrderPartyId(partyId);
                cart.getUserLogin().setString("partyId", partyId);
                inMap.clear();
                inMap.put("userLogin", cart.getUserLogin());
                inMap.put("partyId", partyId);
                inMap.put("roleTypeId", "CUSTOMER");
                dispatcher.runSync("createPartyRole", inMap);
            } catch (GenericServiceException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(e.getMessage());
            }
        }
        // Create a new email address if necessary
        String emailContactMechId = null;
        String emailContactPurposeTypeId = "PRIMARY_EMAIL";
        String emailAddress = decoder.get("EMAIL");
        if (!newParty) {
            EntityCondition cond = EntityCondition.makeCondition(UtilMisc.toList(
                    EntityCondition.makeCondition(UtilMisc.toMap("partyId", partyId, "contactMechTypeId", "EMAIL_ADDRESS")),
                    EntityCondition.makeCondition(EntityFunction.UPPER_FIELD("infoString"), EntityComparisonOperator.EQUALS, EntityFunction.UPPER(emailAddress)),
                    EntityUtil.getFilterByDateExpr()

           ));
            try {
                GenericValue matchingEmail = EntityUtil.getFirst(delegator.findList("PartyAndContactMech", cond, null, UtilMisc.toList("fromDate"), null, false));
                if (matchingEmail != null) {
                    emailContactMechId = matchingEmail.getString("contactMechId");
                } else {
                    // No email found so we'll need to create one but first check if it should be PRIMARY or just BILLING
                    cond = EntityCondition.makeCondition(UtilMisc.toList(
                            EntityCondition.makeCondition(UtilMisc.toMap("partyId", partyId, "contactMechTypeId", "EMAIL_ADDRESS", "contactMechPurposeTypeId", "PRIMARY_EMAIL")),
                            EntityCondition.makeConditionDate("contactFromDate", "contactThruDate"),
                            EntityCondition.makeConditionDate("purposeFromDate", "purposeThruDate")));
                    List<GenericValue> primaryEmails = delegator.findList("PartyContactWithPurpose", cond, null, null, null, false);
                    if (UtilValidate.isNotEmpty(primaryEmails)) emailContactPurposeTypeId = "BILLING_EMAIL";
                }
            } catch (GenericEntityException e) {
                Debug.logError(e, module);
            }
        }
        if (emailContactMechId == null) {
            inMap.clear();
            inMap.put("userLogin", cart.getUserLogin());
            inMap.put("contactMechPurposeTypeId", emailContactPurposeTypeId);
            inMap.put("emailAddress", emailAddress);
            inMap.put("partyId", partyId);
            inMap.put("roleTypeId", "CUSTOMER");
            inMap.put("verified", "Y");  // Going to assume PayPal has taken care of this for us
            inMap.put("fromDate", UtilDateTime.nowTimestamp());
            try {
                outMap = dispatcher.runSync("createPartyEmailAddress", inMap);
                emailContactMechId = (String) outMap.get("contactMechId");
            } catch (GenericServiceException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(e.getMessage());
            }
        }
        cart.addContactMech("ORDER_EMAIL", emailContactMechId);

        // Phone number
        String phoneNumber = decoder.get("PHONENUM");
        String phoneContactId = null;
        if (phoneNumber != null) {
            inMap.clear();
            if (phoneNumber.startsWith("+")) {
                // International, format is +XXX XXXXXXXX which we'll split into countryCode + contactNumber
                String[] phoneNumbers = phoneNumber.split(" ");
                inMap.put("countryCode", StringUtil.removeNonNumeric(phoneNumbers[0]));
                inMap.put("contactNumber", phoneNumbers[1]);
            } else {
                // U.S., format is XXX-XXX-XXXX which we'll split into areaCode + contactNumber
                inMap.put("countryCode", "1");
                String[] phoneNumbers = phoneNumber.split("-");
                inMap.put("areaCode", phoneNumbers[0]);
                inMap.put("contactNumber", phoneNumbers[1] + phoneNumbers[2]);
            }
            inMap.put("userLogin", cart.getUserLogin());
            inMap.put("partyId", partyId);
            try {
                outMap = dispatcher.runSync("createUpdatePartyTelecomNumber", inMap);
                phoneContactId = (String) outMap.get("contactMechId");
                cart.addContactMech("PHONE_BILLING", phoneContactId);
            } catch (GenericServiceException e) {
                Debug.logError(e, module);
            }
        }
        // Create a new Postal Address if necessary
        String postalContactId = null;
        boolean needsShippingPurpose = true;
        // if the cart for some reason already has a billing address, we'll leave it be
        boolean needsBillingPurpose = (cart.getContactMech("BILLING_LOCATION") == null);
        Map<String, Object> postalMap = FastMap.newInstance();
        postalMap.put("toName", decoder.get("SHIPTONAME"));
        postalMap.put("address1", decoder.get("SHIPTOSTREET"));
        postalMap.put("address2", decoder.get("SHIPTOSTREET2"));
        postalMap.put("city", decoder.get("SHIPTOCITY"));
        String countryGeoId = PayPalServices.getCountryGeoIdFromGeoCode(decoder.get("SHIPTOCOUNTRYCODE"), delegator);
        postalMap.put("countryGeoId", countryGeoId);
        postalMap.put("stateProvinceGeoId", parseStateProvinceGeoId(decoder.get("SHIPTOSTATE"), countryGeoId, delegator));
        postalMap.put("postalCode", decoder.get("SHIPTOZIP"));
        if (!newParty) {
            // We want an exact match only
            EntityCondition cond = EntityCondition.makeCondition(UtilMisc.toList(
                    EntityCondition.makeCondition(postalMap),
                    EntityCondition.makeCondition(UtilMisc.toMap("attnName", null, "directions", null, "postalCodeExt", null,"postalCodeGeoId", null)),
                    EntityUtil.getFilterByDateExpr(),
                    EntityCondition.makeCondition("partyId", partyId)
           ));
            try {
                GenericValue postalMatch = EntityUtil.getFirst(delegator.findList("PartyAndPostalAddress", cond, null, UtilMisc.toList("fromDate"), null, false));
                if (postalMatch != null) {
                    postalContactId = postalMatch.getString("contactMechId");
                    EntityCondition purposeCond = EntityCondition.makeCondition(UtilMisc.toList(
                            EntityCondition.makeCondition(UtilMisc.toMap("partyId", partyId, "contactMechId", postalContactId)),
                            EntityUtil.getFilterByDateExpr()
                   ));
                    List<GenericValue> postalPurposes = delegator.findList("PartyContactMechPurpose", purposeCond, null, null, null, false);
                    List<Object> purposeStrings = EntityUtil.getFieldListFromEntityList(postalPurposes, "contactMechPurposeTypeId", false);
                    if (UtilValidate.isNotEmpty(purposeStrings) && purposeStrings.contains("SHIPPING_LOCATION")) {
                        needsShippingPurpose = false;
                    }
                    if (needsBillingPurpose && UtilValidate.isNotEmpty(purposeStrings) && purposeStrings.contains("BILLING_LOCATION")) {
                        needsBillingPurpose = false;
                    }
                }
            } catch (GenericEntityException e) {
                Debug.logError(e, module);
            }
        }
        if (postalContactId == null) {
            postalMap.put("userLogin", cart.getUserLogin());
            postalMap.put("fromDate", UtilDateTime.nowTimestamp());
            try {
                outMap = dispatcher.runSync("createPartyPostalAddress", postalMap);
                postalContactId = (String) outMap.get("contactMechId");
            } catch (GenericServiceException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(e.getMessage());
            }
        }
        if (needsShippingPurpose || needsBillingPurpose) {
            inMap.clear();
            inMap.put("userLogin", cart.getUserLogin());
            inMap.put("contactMechId", postalContactId);
            inMap.put("partyId", partyId);
            try {
                if (needsShippingPurpose) {
                    inMap.put("contactMechPurposeTypeId", "SHIPPING_LOCATION");
                    dispatcher.runSync("createPartyContactMechPurpose", inMap);
                }
                if (needsBillingPurpose) {
                    inMap.put("contactMechPurposeTypeId", "BILLING_LOCATION");
                    dispatcher.runSync("createPartyContactMechPurpose", inMap);
                }
            } catch (GenericServiceException e) {
                // Not the end of the world, we'll carry on
                Debug.log(e.getMessage());
            }
        }

        // Load the selected shipping method - thanks to PayPal's less than sane API all we've to work with is the shipping option label
        // that was shown to the customer
        String shipMethod = decoder.get("SHIPPINGOPTIONNAME");
        if ("Calculated Offline".equals(shipMethod)) {
            cart.setCarrierPartyId("_NA_");
            cart.setShipmentMethodTypeId("NO_SHIPPING");
        } else {
            String[] shipMethodSplit = shipMethod.split(" - ");
            cart.setCarrierPartyId(shipMethodSplit[0]);
            String shippingMethodTypeDesc = StringUtils.join(shipMethodSplit, " - ", 1, shipMethodSplit.length);
            try {
                EntityCondition cond = EntityCondition.makeCondition(
                        UtilMisc.toMap("productStoreId", cart.getProductStoreId(), "partyId", shipMethodSplit[0], "roleTypeId", "CARRIER", "description", shippingMethodTypeDesc)
               );
                GenericValue shipmentMethod = EntityUtil.getFirst(delegator.findList("ProductStoreShipmentMethView", cond, null, null, null, false));
                cart.setShipmentMethodTypeId(shipmentMethod.getString("shipmentMethodTypeId"));
            } catch (GenericEntityException e1) {
                Debug.logError(e1, module);
            }
        }
        //Get rid of any excess ship groups
        List<CartShipInfo> shipGroups = cart.getShipGroups();
        for (int i = 1; i < shipGroups.size(); i++) {
            Map<ShoppingCartItem, BigDecimal> items = cart.getShipGroupItems(i);
            for (Map.Entry<ShoppingCartItem, BigDecimal> entry : items.entrySet()) {
                cart.positionItemToGroup(entry.getKey(), entry.getValue(), i, 0, false);
            }
        }
        cart.cleanUpShipGroups();
        cart.setShippingContactMechId(postalContactId);
        Map<String, Object> result = ShippingEvents.getShipGroupEstimate(dispatcher, delegator, cart, 0);
        if (result.get(ModelService.RESPONSE_MESSAGE).equals(ModelService.RESPOND_ERROR)) {
            return ServiceUtil.returnError((String) result.get(ModelService.ERROR_MESSAGE));
        }

        BigDecimal shippingTotal = (BigDecimal) result.get("shippingTotal");
        if (shippingTotal == null) {
            shippingTotal = BigDecimal.ZERO;
        }
        cart.setItemShipGroupEstimate(shippingTotal, 0);
        CheckOutHelper cho = new CheckOutHelper(dispatcher, delegator, cart);
        try {
            cho.calcAndAddTax();
        } catch (GeneralException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

        // Create the PayPal payment method
        inMap.clear();
        inMap.put("userLogin", cart.getUserLogin());
        inMap.put("partyId", partyId);
        inMap.put("contactMechId", postalContactId);
        inMap.put("fromDate", UtilDateTime.nowTimestamp());
        inMap.put("payerId", decoder.get("PAYERID"));
        inMap.put("expressCheckoutToken", token);
        inMap.put("payerStatus", decoder.get("PAYERSTATUS"));

        try {
            outMap = dispatcher.runSync("createPayPalPaymentMethod", inMap);
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }
        String paymentMethodId = (String) outMap.get("paymentMethodId");

        cart.clearPayments();
        BigDecimal maxAmount = cart.getGrandTotal().setScale(2, BigDecimal.ROUND_HALF_UP);
        cart.addPaymentAmount(paymentMethodId, maxAmount, true);

        return ServiceUtil.returnSuccess();

    }

    // Note we're not doing a lot of error checking here as this method is really only used
    // to confirm the order with PayPal, the subsequent authorizations will handle any errors
    // that may occur.
    public static Map<String, Object> doExpressCheckout(DispatchContext dctx, Map<String, Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
        OrderReadHelper orh = new OrderReadHelper(delegator, paymentPref.getString("orderId"));
        Locale locale = (Locale) context.get("locale");

        GenericValue payPalPaymentSetting = getPaymentMethodGatewayPayPal(dctx, context, null);
        GenericValue payPalPaymentMethod = null;
        try {
            payPalPaymentMethod = paymentPref.getRelatedOne("PaymentMethod");
            payPalPaymentMethod = payPalPaymentMethod.getRelatedOne("PayPalPaymentMethod");
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }
        BigDecimal processAmount = paymentPref.getBigDecimal("maxAmount");

        NVPEncoder encoder = new NVPEncoder();
        encoder.add("METHOD", "DoExpressCheckoutPayment");
        encoder.add("TOKEN", payPalPaymentMethod.getString("expressCheckoutToken"));
        encoder.add("PAYMENTACTION", "Order");
        encoder.add("PAYERID", payPalPaymentMethod.getString("payerId"));
        // set the amount
        encoder.add("AMT", processAmount.setScale(2).toPlainString());
        encoder.add("CURRENCYCODE", orh.getCurrency());
        BigDecimal grandTotal = orh.getOrderGrandTotal();
        BigDecimal shippingTotal = orh.getShippingTotal().setScale(2, BigDecimal.ROUND_HALF_UP);
        BigDecimal taxTotal = orh.getTaxTotal().setScale(2, BigDecimal.ROUND_HALF_UP);
        BigDecimal subTotal = grandTotal.subtract(shippingTotal).subtract(taxTotal).setScale(2, BigDecimal.ROUND_HALF_UP);
        encoder.add("ITEMAMT", subTotal.toPlainString());
        encoder.add("SHIPPINGAMT", shippingTotal.toPlainString());
        encoder.add("TAXAMT", taxTotal.toPlainString());

        NVPDecoder decoder = null;
        try {
            decoder = sendNVPRequest(payPalPaymentSetting, encoder);
        } catch (PayPalException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }
        if (decoder == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPayPalUnknownError", locale));
        }

        Map<String, String> errorMessages = getErrorMessageMap(decoder);
        if (UtilValidate.isNotEmpty(errorMessages)) {
            if (errorMessages.containsKey("10417")) {
                // "The transaction cannot complete successfully,  Instruct the customer to use an alternative payment method"
                // I've only encountered this once and there's no indication of the cause so the temporary solution is to try again
                boolean retry = context.get("_RETRY_") == null || (Boolean) context.get("_RETRY_");
                if (retry) {
                    context.put("_RETRY_", false);
                    return PayPalServices.doExpressCheckout(dctx, context);
                }
            }
            return ServiceUtil.returnError(UtilMisc.toList(errorMessages.values()));
        }

        Map<String, Object> inMap = FastMap.newInstance();
        inMap.put("userLogin", userLogin);
        inMap.put("paymentMethodId", payPalPaymentMethod.get("paymentMethodId"));
        inMap.put("transactionId", decoder.get("TRANSACTIONID"));

        Map<String, Object> outMap = null;
        try {
            outMap = dispatcher.runSync("updatePayPalPaymentMethod", inMap);
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }
        if (ServiceUtil.isError(outMap)) {
            Debug.logError(ServiceUtil.getErrorMessage(outMap), module);
            return outMap;
        }
        return ServiceUtil.returnSuccess();
    }

    public static Map<String, Object> doAuthorization(DispatchContext dctx, Map<String, Object> context) {
        Delegator delegator = dctx.getDelegator();
        String orderId = (String) context.get("orderId");
        BigDecimal processAmount = (BigDecimal) context.get("processAmount");
        GenericValue payPalPaymentMethod = (GenericValue) context.get("payPalPaymentMethod");
        OrderReadHelper orh = new OrderReadHelper(delegator, orderId);
        GenericValue payPalConfig = getPaymentMethodGatewayPayPal(dctx, context, PaymentGatewayServices.AUTH_SERVICE_TYPE);
        Locale locale = (Locale) context.get("locale");

        NVPEncoder encoder = new NVPEncoder();
        encoder.add("METHOD", "DoAuthorization");
        encoder.add("TRANSACTIONID", payPalPaymentMethod.getString("transactionId"));
        encoder.add("AMT", processAmount.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
        encoder.add("TRANSACTIONENTITY", "Order");
        String currency = (String) context.get("currency");
        if (currency == null) {
            currency = orh.getCurrency();
        }
        encoder.add("CURRENCYCODE", currency);

        NVPDecoder decoder = null;
        try {
            decoder = sendNVPRequest(payPalConfig, encoder);
        } catch (PayPalException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

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

        Map<String, Object> result = ServiceUtil.returnSuccess();
        Map<String, String> errors = getErrorMessageMap(decoder);
        if (UtilValidate.isNotEmpty(errors)) {
            result.put("authResult", false);
            result.put("authRefNum", "N/A");
            result.put("processAmount", BigDecimal.ZERO);
            if (errors.size() == 1) {
                Map.Entry<String, String> error = errors.entrySet().iterator().next();
                result.put("authCode", error.getKey());
                result.put("authMessage", error.getValue());
            } else {
                result.put("authMessage", "Multiple errors occurred, please refer to the gateway response messages");
                result.put("internalRespMsgs", errors);
            }
        } else {
            result.put("authResult", true);
            result.put("processAmount", new BigDecimal(decoder.get("AMT")));
            result.put("authRefNum", decoder.get("TRANSACTIONID"));
        }
        //TODO: Look into possible PAYMENTSTATUS and PENDINGREASON return codes, it is unclear what should be checked for this type of transaction
        return result;
    }

    public static Map<String, Object> doCapture(DispatchContext dctx, Map<String, Object> context) {
        GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
        BigDecimal captureAmount = (BigDecimal) context.get("captureAmount");
        GenericValue payPalConfig = getPaymentMethodGatewayPayPal(dctx, context, PaymentGatewayServices.AUTH_SERVICE_TYPE);
        GenericValue authTrans = (GenericValue) context.get("authTrans");
        Locale locale = (Locale) context.get("locale");
        if (authTrans == null) {
            authTrans = PaymentGatewayServices.getAuthTransaction(paymentPref);
        }

        NVPEncoder encoder = new NVPEncoder();
        encoder.add("METHOD", "DoCapture");
        encoder.add("AUTHORIZATIONID", authTrans.getString("referenceNum"));
        encoder.add("AMT", captureAmount.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
        encoder.add("CURRENCYCODE", authTrans.getString("currencyUomId"));
        encoder.add("COMPLETETYPE", "NotComplete");

        NVPDecoder decoder = null;
        try {
            decoder = sendNVPRequest(payPalConfig, encoder);
        } catch (PayPalException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

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

        Map<String, Object> result = ServiceUtil.returnSuccess();
        Map<String, String> errors = getErrorMessageMap(decoder);
        if (UtilValidate.isNotEmpty(errors)) {
            result.put("captureResult", false);
            result.put("captureRefNum", "N/A");
            result.put("captureAmount", BigDecimal.ZERO);
            if (errors.size() == 1) {
                Map.Entry<String, String> error = errors.entrySet().iterator().next();
                result.put("captureCode", error.getKey());
                result.put("captureMessage", error.getValue());
            } else {
                result.put("captureMessage", "Multiple errors occurred, please refer to the gateway response messages");
                result.put("internalRespMsgs", errors);
            }
        } else {
            result.put("captureResult", true);
            result.put("captureAmount", new BigDecimal(decoder.get("AMT")));
            result.put("captureRefNum", decoder.get("TRANSACTIONID"));
        }
        //TODO: Look into possible PAYMENTSTATUS and PENDINGREASON return codes, it is unclear what should be checked for this type of transaction
        return result;
    }

    public static Map<String, Object> doVoid(DispatchContext dctx, Map<String, Object> context) {
        GenericValue payPalConfig = getPaymentMethodGatewayPayPal(dctx, context, null);
        Locale locale = (Locale) context.get("locale");
        if (payPalConfig == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPayPalPaymentGatewayConfigCannotFind", locale));
        }
        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
        GenericValue authTrans = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference);
        NVPEncoder encoder = new NVPEncoder();
        encoder.add("METHOD", "DoVoid");
        encoder.add("AUTHORIZATIONID", authTrans.getString("referenceNum"));
        NVPDecoder decoder = null;
        try {
            decoder = sendNVPRequest(payPalConfig, encoder);
        } catch (PayPalException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

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

        Map<String, Object> result = ServiceUtil.returnSuccess();
        Map<String, String> errors = getErrorMessageMap(decoder);
        if (UtilValidate.isNotEmpty(errors)) {
            result.put("releaseResult", false);
            result.put("releaseRefNum", authTrans.getString("referenceNum"));
            result.put("releaseAmount", BigDecimal.ZERO);
            if (errors.size() == 1) {
                Map.Entry<String, String> error = errors.entrySet().iterator().next();
                result.put("releaseCode", error.getKey());
                result.put("releaseMessage", error.getValue());
            } else {
                result.put("releaseMessage", "Multiple errors occurred, please refer to the gateway response messages");
                result.put("internalRespMsgs", errors);
            }
        } else {
            result.put("releaseResult", true);
            // PayPal voids the entire order amount minus any captures, that's a little difficult to figure out here
            // so until further testing proves we should do otherwise I'm just going to return requested void amount
            result.put("releaseAmount", context.get("releaseAmount"));
            result.put("releaseRefNum", decoder.get("AUTHORIZATIONID"));
        }
        return result;
    }

    public static Map<String, Object> doRefund (DispatchContext dctx, Map<String, Object> context) {
        Locale locale = (Locale) context.get("locale");
        GenericValue payPalConfig = getPaymentMethodGatewayPayPal(dctx, context, null);
        if (payPalConfig == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPayPalPaymentGatewayConfigCannotFind", locale));
        }
        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
        GenericValue captureTrans = PaymentGatewayServices.getCaptureTransaction(orderPaymentPreference);
        BigDecimal refundAmount = (BigDecimal) context.get("refundAmount");
        NVPEncoder encoder = new NVPEncoder();
        encoder.add("METHOD", "RefundTransaction");
        encoder.add("TRANSACTIONID", captureTrans.getString("referenceNum"));
        encoder.add("REFUNDTYPE", "Partial");
        encoder.add("CURRENCYCODE", captureTrans.getString("currencyUomId"));
        encoder.add("AMT", refundAmount.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
        encoder.add("NOTE", "Order #" + orderPaymentPreference.getString("orderId"));
        NVPDecoder decoder = null;
        try {
            decoder = sendNVPRequest(payPalConfig, encoder);
        } catch (PayPalException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

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

        Map<String, Object> result = ServiceUtil.returnSuccess();
        Map<String, String> errors = getErrorMessageMap(decoder);
        if (UtilValidate.isNotEmpty(errors)) {
            result.put("refundResult", false);
            result.put("refundRefNum", captureTrans.getString("referenceNum"));
            result.put("refundAmount", BigDecimal.ZERO);
            if (errors.size() == 1) {
                Map.Entry<String, String> error = errors.entrySet().iterator().next();
                result.put("refundCode", error.getKey());
                result.put("refundMessage", error.getValue());
            } else {
                result.put("refundMessage", "Multiple errors occurred, please refer to the gateway response messages");
                result.put("internalRespMsgs", errors);
            }
        } else {
            result.put("refundResult", true);
            result.put("refundAmount", new BigDecimal(decoder.get("GROSSREFUNDAMT")));
            result.put("refundRefNum", decoder.get("REFUNDTRANSACTIONID"));
        }
        return result;
    }

    private static GenericValue getPaymentMethodGatewayPayPal(DispatchContext dctx, Map<String, ? extends Object> context, String paymentServiceTypeEnumId) {
        Delegator delegator = dctx.getDelegator();
        String paymentGatewayConfigId = (String) context.get("paymentGatewayConfigId");
        GenericValue payPalGatewayConfig = null;

        if (paymentGatewayConfigId == null) {
            String productStoreId = null;
            GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
            if (orderPaymentPreference != null) {
                OrderReadHelper orh = new OrderReadHelper(delegator, orderPaymentPreference.getString("orderId"));
                productStoreId = orh.getProductStoreId();
            } else {
                ShoppingCart cart = (ShoppingCart) context.get("cart");
                if (cart != null) {
                    productStoreId = cart.getProductStoreId();
                }
            }
            if (productStoreId != null) {
                GenericValue payPalPaymentSetting = ProductStoreWorker.getProductStorePaymentSetting(delegator, productStoreId, "EXT_PAYPAL", paymentServiceTypeEnumId, true);
                if (payPalPaymentSetting != null) {
                    paymentGatewayConfigId = payPalPaymentSetting.getString("paymentGatewayConfigId");
                }
            }
        }
        if (paymentGatewayConfigId != null) {
            try {
                payPalGatewayConfig = delegator.findOne("PaymentGatewayPayPal", true, "paymentGatewayConfigId", paymentGatewayConfigId);
            } catch (GenericEntityException e) {
                Debug.logError(e, module);
            }
        }
        return payPalGatewayConfig;
    }

    private static NVPDecoder sendNVPRequest(GenericValue payPalConfig, NVPEncoder encoder) throws PayPalException {
        NVPCallerServices caller = new NVPCallerServices();
        try {
            APIProfile profile = ProfileFactory.createSignatureAPIProfile();
            profile.setAPIUsername(payPalConfig.getString("apiUserName"));
            profile.setAPIPassword(payPalConfig.getString("apiPassword"));
            profile.setSignature(payPalConfig.getString("apiSignature"));
            profile.setEnvironment(payPalConfig.getString("apiEnvironment"));
            caller.setAPIProfile(profile);
        } catch (PayPalException e) {
            Debug.logError(e.getMessage(), module);
        }

        String requestMessage = encoder.encode();
        String responseMessage = caller.call(requestMessage);

        NVPDecoder decoder = new NVPDecoder();
        decoder.decode(responseMessage);
        if (!"Success".equals(decoder.get("ACK"))) {
            Debug.logError("A response other than success was received from PayPal: " + responseMessage, module);
        }

        return decoder;
    }

    private static String getCountryGeoIdFromGeoCode(String geoCode, Delegator delegator) {
        String geoId = null;
        try {
            EntityCondition cond =EntityCondition.makeCondition(UtilMisc.toMap("geoTypeId", "COUNTRY", "geoCode", geoCode));
            GenericValue countryGeo = EntityUtil.getFirst(delegator.findList("Geo", cond, null, null, null, true));
            if (countryGeo != null) {
                geoId = countryGeo.getString("geoId");
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }
        return geoId;
    }

    private static String parseStateProvinceGeoId(String payPalShipToState, String countryGeoId, Delegator delegator) {
        String lookupField = "geoName";
        List<EntityCondition> conditionList = FastList.newInstance();
        conditionList.add(EntityCondition.makeCondition("geoAssocTypeId", "REGIONS"));
        if ("USA".equals(countryGeoId) || "CAN".equals(countryGeoId)) {
            // PayPal returns two letter code for US and Canadian States/Provinces
            String geoTypeId = "USA".equals(countryGeoId) ? "STATE" : "PROVINCE";
            conditionList.add(EntityCondition.makeCondition("geoTypeId", geoTypeId));
            lookupField = "geoCode";
        }
        conditionList.add(EntityCondition.makeCondition("geoIdFrom", countryGeoId));
        conditionList.add(EntityCondition.makeCondition(lookupField, payPalShipToState));
        EntityCondition cond = EntityCondition.makeCondition(conditionList);
        GenericValue geoAssocAndGeoTo = null;
        try {
            geoAssocAndGeoTo = EntityUtil.getFirst(delegator.findList("GeoAssocAndGeoTo", cond, null, null, null, true));
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }
        if (geoAssocAndGeoTo != null) {
            return geoAssocAndGeoTo.getString("geoId");
        }
        return null;
    }

    @SuppressWarnings("serial")
    public static class TokenWrapper implements Serializable {
        String theString;
        public TokenWrapper(String theString) {
            this.theString = theString;
        }

        @Override
        public boolean equals(Object o) {
            if (o == null) return false;
            if (!(o instanceof TokenWrapper)) return false;
            TokenWrapper other = (TokenWrapper) o;
            return theString.equals(other.theString);
        }
        @Override
        public int hashCode() {
            return theString.hashCode();
        }
    }
}
