/*******************************************************************************
 * 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.EntityQuery;
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 = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").cache().queryOne();
            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.setAllShipmentMethodTypeId(shipMethod.getString("shipmentMethodTypeId"));
            cart.setAllCarrierPartyId(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 = EntityQuery.use(delegator).from("PostalAddress").where("contactMechId", contactMechId).queryOne();
            postalAddress.remove();
            GenericValue contactMech = EntityQuery.use(delegator).from("ContactMech").where("contactMechId", contactMechId).queryOne();
            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 = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "anonymous").queryOne();
                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 = EntityQuery.use(delegator).from("Party").where("partyId", partyId).queryOne();
            } 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))

           ));
            try {
                GenericValue matchingEmail = EntityQuery.use(delegator).from("PartyAndContactMech").where(cond).orderBy("fromDate").filterByDate().queryFirst();
                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
                    long primaryEmails = EntityQuery.use(delegator)
                            .from("PartyContactWithPurpose")
                            .where("partyId", partyId, 
                                    "contactMechTypeId", "EMAIL_ADDRESS", 
                                    "contactMechPurposeTypeId", "PRIMARY_EMAIL")
                            .filterByDate("contactFromDate", "contactThruDate", "purposeFromDate", "purposeThruDate")
                            .queryCount();
                    if (primaryEmails > 0) 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)),
                    EntityCondition.makeCondition("partyId", partyId)
           ));
            try {
                GenericValue postalMatch = EntityQuery.use(delegator).from("PartyAndPostalAddress")
                        .where(cond).orderBy("fromDate").filterByDate().queryFirst();
                if (postalMatch != null) {
                    postalContactId = postalMatch.getString("contactMechId");
                    List<GenericValue> postalPurposes = EntityQuery.use(delegator).from("PartyContactMechPurpose")
                            .where("partyId", partyId, "contactMechId", postalContactId)
                            .filterByDate().queryList();
                    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.logInfo(e.getMessage(), module);
            }
        }

        // 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.setAllCarrierPartyId("_NA_");
            cart.setAllShipmentMethodTypeId("NO_SHIPPING");
        } else {
            String[] shipMethodSplit = shipMethod.split(" - ");
            cart.setAllCarrierPartyId(shipMethodSplit[0]);
            String shippingMethodTypeDesc = StringUtils.join(shipMethodSplit, " - ", 1, shipMethodSplit.length);
            try {
                GenericValue shipmentMethod = EntityQuery.use(delegator)
                        .from("ProductStoreShipmentMethView")
                        .where("productStoreId", cart.getProductStoreId(), 
                                "partyId", shipMethodSplit[0], 
                                "roleTypeId", "CARRIER", 
                                "description", shippingMethodTypeDesc)
                        .queryFirst();
                cart.setAllShipmentMethodTypeId(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.setAllShippingContactMechId(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", false);
            payPalPaymentMethod = payPalPaymentMethod.getRelatedOne("PayPalPaymentMethod", false);
        } 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 = EntityQuery.use(delegator).from("PaymentGatewayPayPal").where("paymentGatewayConfigId", paymentGatewayConfigId).cache().queryOne();
            } 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 {
            GenericValue countryGeo = EntityQuery.use(delegator).from("Geo")
                    .where("geoTypeId", "COUNTRY", "geoCode", geoCode).cache().queryFirst();
            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 = EntityQuery.use(delegator).from("GeoAssocAndGeoTo").where(cond).cache().queryFirst();
            
        } 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();
        }
    }
}
