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

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

import javolution.util.FastMap;

import org.ofbiz.accounting.payment.PaymentGatewayServices;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.HttpClient;
import org.ofbiz.base.util.HttpClientException;
import org.ofbiz.base.util.UtilDateTime;
import org.ofbiz.base.util.UtilFormatOut;
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.service.DispatchContext;
import org.ofbiz.service.ModelService;
import org.ofbiz.service.ServiceUtil;

import com.ibm.icu.util.Calendar;

public class AIMPaymentServices {

    public static final String module = AIMPaymentServices.class.getName();
    public final static String resource = "AccountingUiLabels";

    // The list of refund failure response codes that would cause the ccRefund service
    // to attempt to void the refund's associated authorization transaction.  This list
    // contains the responses where the voiding does not need to be done within a certain
    // time limit
    private static final List<String> VOIDABLE_RESPONSES_NO_TIME_LIMIT = UtilMisc.toList("50");

    // A list of refund failure response codes that would cause the ccRefund service
    // to first check whether the refund's associated authorization transaction has occurred
    // within a certain time limit, and if so, cause it to void the transaction
    private static final List<String> VOIDABLE_RESPONSES_TIME_LIMIT = UtilMisc.toList("54");

    // The number of days in the time limit when one can safely consider an unsettled
    // transaction to be still valid
    private static final int TIME_LIMIT_VERIFICATION_DAYS = 120;

    private static Properties AIMProperties = null;

    // A routine to check whether a given refund failure response code will cause the
    // ccRefund service to attempt to void the refund's associated authorization transaction
    private static boolean isVoidableResponse(String responseCode) {
        return
            VOIDABLE_RESPONSES_NO_TIME_LIMIT.contains(responseCode) ||
            VOIDABLE_RESPONSES_TIME_LIMIT.contains(responseCode);
    }

    public static Map<String, Object> ccAuth(DispatchContext ctx, Map<String, Object> context) {
        Delegator delegator = ctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> results = ServiceUtil.returnSuccess();
        Map<String, Object> request = FastMap.newInstance();
        Properties props = buildAIMProperties(context, delegator);
        buildMerchantInfo(context, props, request);
        buildGatewayResponeConfig(context, props, request);
        buildCustomerBillingInfo(context, props, request);
        buildEmailSettings(context, props, request);
        buildInvoiceInfo(context, props, request);
        props.put("transType", "AUTH_ONLY");
        buildAuthTransaction(context, props, request);
        Map<String, Object> validateResults = validateRequest(context, props, request);
        String respMsg = (String)validateResults.get(ModelService.RESPONSE_MESSAGE);
        if (ModelService.RESPOND_ERROR.equals(respMsg)) {
            results.put(ModelService.ERROR_MESSAGE, "Validation Failed - invalid values");
            return results;
        }
        Map<String, Object> reply = processCard(request, props, locale);
        //now we need to process the result
        processAuthTransResult(request, reply, results);
        return results;
    }

    public static Map<String, Object> ccCapture(DispatchContext ctx, Map<String, Object> context) {
        Locale locale = (Locale) context.get("locale");
        Delegator delegator = ctx.getDelegator();
        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
        GenericValue creditCard = null;
        try {
            creditCard = delegator.getRelatedOne("CreditCard",orderPaymentPreference);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentUnableToGetCCInfo", locale));
        }
        GenericValue authTransaction = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference);
        if (authTransaction == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentTransactionAuthorizationNotFoundCannotCapture", locale));
        }
        context.put("creditCard", creditCard);
        context.put("authTransaction", authTransaction);
        Map<String, Object> results = ServiceUtil.returnSuccess();
        Map<String, Object> request = FastMap.newInstance();
        Properties props = buildAIMProperties(context, delegator);
        buildMerchantInfo(context, props, request);
        buildGatewayResponeConfig(context, props, request);
        buildCustomerBillingInfo(context, props, request);
        buildEmailSettings(context, props, request);
        request.put("x_Invoice_Num","Order " + orderPaymentPreference.getString("orderId"));
        // PRIOR_AUTH_CAPTURE is the right one to use, since we already have an authorization from the authTransaction.
        // CAPTURE_ONLY is a "force" transaction to be used if there is no prior authorization
        props.put("transType", "PRIOR_AUTH_CAPTURE");
        //props.put("transType","CAPTURE_ONLY");
        props.put("cardtype", creditCard.get("cardType"));
        buildCaptureTransaction(context,props,request);
        Map<String, Object> validateResults = validateRequest(context, props, request);
        String respMsg = (String)validateResults.get(ModelService.RESPONSE_MESSAGE);
        if (ModelService.RESPOND_ERROR.equals(respMsg)) {
            results.put(ModelService.ERROR_MESSAGE, "Validation Failed - invalid values");
            return results;
        }
        Map<String, Object> reply = processCard(request, props, locale);
        processCaptureTransResult(request, reply, results);
        // if there is no captureRefNum, then the capture failed
        if (results.get("captureRefNum") == null) {
             return ServiceUtil.returnError((String) results.get("captureMessage"));
        }
        return results;
    }

    public static Map<String, Object> ccRefund(DispatchContext ctx, Map<String, Object> context) {
        Locale locale = (Locale) context.get("locale");
        Delegator delegator = ctx.getDelegator();
        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
        GenericValue creditCard = null;
        try {
            creditCard = delegator.getRelatedOne("CreditCard", orderPaymentPreference);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentUnableToGetCCInfo", locale));
        }
        GenericValue authTransaction = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference);
        if (authTransaction == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentTransactionAuthorizationNotFoundCannotRefund", locale));
        }
        context.put("creditCard",creditCard);
        context.put("authTransaction",authTransaction);
        Map<String, Object> results = ServiceUtil.returnSuccess();
        Map<String, Object> request = FastMap.newInstance();
        Properties props = buildAIMProperties(context, delegator);
        buildMerchantInfo(context, props, request);
        buildGatewayResponeConfig(context, props, request);
        buildCustomerBillingInfo(context, props, request);
        buildEmailSettings(context, props, request);
        buildInvoiceInfo(context, props, request);
        props.put("transType", "CREDIT");
        props.put("cardtype", creditCard.get("cardType"));
        buildRefundTransaction(context, props, request);
        Map<String, Object> validateResults = validateRequest(context, props, request);
        String respMsg = (String)validateResults.get(ModelService.RESPONSE_MESSAGE);
        if (ModelService.RESPOND_ERROR.equals(respMsg)) {
            results.put(ModelService.ERROR_MESSAGE, "Validation Failed - invalid values");
            return results;
        }
        Map<String, Object> reply = processCard(request, props, locale);
        results.putAll(processRefundTransResult(request, reply));
        boolean refundResult = ((Boolean)results.get("refundResult")).booleanValue();
        String refundFlag = (String)results.get("refundFlag");
        // Since the refund failed, we are going to void the previous authorization against
        // which ccRefunds attempted to issue the refund.  This happens because Authorize.NET requires
        // that settled transactions need to be voided the same day.  unfortunately they provide no method for
        // determining what transactions can be voided and what can be refunded, so we'll have to try it with timestamps
        if (!refundResult && isVoidableResponse(refundFlag)) {
            boolean canDoVoid = false;
            if (VOIDABLE_RESPONSES_TIME_LIMIT.contains(refundFlag)) {
                // We are calculating the timestamp that is at the beginning of a time limit,
                // since we can safely assume that, within this time limit, an unsettled transaction
                // can still be considered valid
                Calendar startCalendar = UtilDateTime.toCalendar(UtilDateTime.nowTimestamp());
                startCalendar.add(Calendar.DATE, -TIME_LIMIT_VERIFICATION_DAYS);
                Timestamp startTimestamp = new java.sql.Timestamp(startCalendar.getTime().getTime());
                Timestamp authTimestamp = authTransaction.getTimestamp("transactionDate");
                if (startTimestamp.before(authTimestamp)) {
                    canDoVoid = true;
                }
            } else {
                // Since there's no time limit to check, the voiding of the transaction will go
                // through as usual
                canDoVoid = true;
            }
            if (canDoVoid) {
                Debug.logWarning("Refund was unsuccessful; will now attempt a VOID transaction.", module);
                BigDecimal authAmountObj = authTransaction.getBigDecimal("amount");
                BigDecimal refundAmountObj = (BigDecimal)context.get("refundAmount");
                BigDecimal authAmount = authAmountObj != null ? authAmountObj : BigDecimal.ZERO;
                BigDecimal refundAmount = refundAmountObj != null ? refundAmountObj : BigDecimal.ZERO;
                if (authAmount.compareTo(refundAmount) == 0) {
                    reply = voidTransaction(authTransaction, context, delegator);
                    if (ServiceUtil.isError(reply)) {
                        return reply;
                    }
                    results = ServiceUtil.returnSuccess();
                    results.putAll(processRefundTransResult(request, reply));
                    return results;
                } else {
                    // TODO: Modify the code to (a) do a void of the whole transaction, and (b)
                    // create a new auth-capture of the difference.
                    return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                            "AccountingAuthorizeNetCannotPerformVoidTransaction", 
                            UtilMisc.toMap("authAmount", authAmount, "refundAmount", refundAmount), locale));
                }
            }
        }
        return results;
    }

    public static Map<String, Object> ccRelease(DispatchContext ctx, Map<String, Object> context) {
        Locale locale = (Locale) context.get("locale");
        Delegator delegator = ctx.getDelegator();
        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
        GenericValue authTransaction = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference);
        if (authTransaction == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentTransactionAuthorizationNotFoundCannotRelease", locale));
        }
        Map<String, Object> reply = voidTransaction(authTransaction, context, delegator);
        if (ServiceUtil.isError(reply)) {
            return reply;
        }
        Map<String, Object> results = ServiceUtil.returnSuccess();
        context.put("x_Amount", context.get("releaseAmount")); // hack for releaseAmount
        results.putAll(processReleaseTransResult(context, reply));
        return results;
    }

    private static Map<String, Object> voidTransaction(GenericValue authTransaction, Map<String, Object> context, Delegator delegator) {
        Locale locale = (Locale) context.get("locale");
        context.put("authTransaction", authTransaction);
        Map<String, Object> results = ServiceUtil.returnSuccess();
        Map<String, Object> request = FastMap.newInstance();
        Properties props = buildAIMProperties(context, delegator);
        buildMerchantInfo(context, props, request);
        buildGatewayResponeConfig(context, props, request);
        buildEmailSettings(context, props, request);
        props.put("transType", "VOID");
        buildVoidTransaction(context, props, request);
        Map<String, Object> validateResults = validateRequest(context, props, request);
        String respMsg = (String)validateResults.get(ModelService.RESPONSE_MESSAGE);
        if (ModelService.RESPOND_ERROR.equals(respMsg)) {
            results.put(ModelService.ERROR_MESSAGE, "Validation Failed - invalid values");
            return results;
        }
        return processCard(request, props, locale);
    }

    public static Map<String, Object> ccCredit(DispatchContext ctx, Map<String, Object> context) {
        Map<String, Object> results = FastMap.newInstance();
        results.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_ERROR);
        results.put(ModelService.ERROR_MESSAGE, "Authorize.net ccCredit unsupported with version 3.1");
        return results;
    }

    public static Map<String, Object> ccAuthCapture(DispatchContext ctx, Map<String, Object> context) {
        Delegator delegator = ctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> results = ServiceUtil.returnSuccess();
        Map<String, Object> request = FastMap.newInstance();
        Properties props = buildAIMProperties(context, delegator);
        buildMerchantInfo(context, props, request);
        buildGatewayResponeConfig(context, props, request);
        buildCustomerBillingInfo(context, props, request);
        buildEmailSettings(context, props, request);
        buildInvoiceInfo(context, props, request);
        props.put("transType", "AUTH_CAPTURE");
        buildAuthTransaction(context, props, request);
        Map<String, Object> validateResults = validateRequest(context, props, request);
        String respMsg = (String)validateResults.get(ModelService.RESPONSE_MESSAGE);
        if (ModelService.RESPOND_ERROR.equals(respMsg)) {
            results.put(ModelService.ERROR_MESSAGE, "Validation Failed - invalid values");
            return results;
        }
        Map<String, Object> reply = processCard(request, props, locale);
        //now we need to process the result
        processAuthCaptureTransResult(request, reply, results);
        // if there is no captureRefNum, then the capture failed
        if (results.get("captureRefNum") == null) {
             return ServiceUtil.returnError((String) results.get("captureMessage"));
        }
        return results;
    }

    private static Map<String, Object> processCard(Map<String, Object> request, Properties props, Locale locale) {
        Map<String, Object> result = FastMap.newInstance();
        String url = props.getProperty("url");
        if (UtilValidate.isEmpty(url)) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingAuthorizeNetTransactionUrlNotFound", locale));
        }
        if (isTestMode()) {
            Debug.logInfo("TEST Authorize.net using url [" + url + "]", module);
            Debug.logInfo("TEST Authorize.net request string " + request.toString(),module);
            Debug.logInfo("TEST Authorize.net properties string " + props.toString(),module);
        }
        
        // card present has a different layout from standard AIM; this determines how to parse the response
        int apiType = UtilValidate.isEmpty(props.get("cpMarketType")) ? AuthorizeResponse.AIM_RESPONSE : AuthorizeResponse.CP_RESPONSE;
        
        try {
            HttpClient httpClient = new HttpClient(url, request);
            String certificateAlias = props.getProperty("certificateAlias");
            httpClient.setClientCertificateAlias(certificateAlias);
            String httpResponse = httpClient.post();
            Debug.logInfo("transaction response: " + httpResponse,module);
            AuthorizeResponse ar = new AuthorizeResponse(httpResponse, apiType);            
            if (ar.isApproved()) {            
                result.put("authResult", Boolean.TRUE);
            } else {
                result.put("authResult", Boolean.FALSE);
                if (Debug.infoOn()) {
                    Debug.logInfo("transactionId:  " + ar.getTransactionId(), module);
                    Debug.logInfo("responseCode:   " + ar.getResponseCode(), module);
                    Debug.logInfo("responseReason: " + ar.getReasonCode(), module);
                    Debug.logInfo("reasonText:     " + ar.getReasonText(), module);
                }
            }
            result.put("httpResponse", httpResponse);
            result.put("authorizeResponse", ar);
        } catch (HttpClientException e) {
            Debug.logInfo(e, "Could not complete Authorize.Net transaction: " + e.toString(),module);
        }
        result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
        return result;
    }

    private static boolean isTestMode() {
        return "true".equalsIgnoreCase((String)AIMProperties.get("testReq"));
    }

    private static Properties buildAIMProperties(Map<String, Object> context, Delegator delegator) {
        String paymentGatewayConfigId = (String) context.get("paymentGatewayConfigId");
        String configStr = (String) context.get("paymentConfig");
        if (configStr == null) {
            configStr = "payment.properties";
        }
        GenericValue cc = (GenericValue)context.get("creditCard");
        String url = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "transactionUrl", configStr, "payment.authorizedotnet.url");
        String certificateAlias = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "certificateAlias", configStr, "payment.authorizedotnet.certificateAlias");
        String ver = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "apiVersion", configStr, "payment.authorizedotnet.version");
        String delimited = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "delimitedData", configStr, "payment.authorizedotnet.delimited");
        String delimiter = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "delimiterChar", configStr, "payment.authorizedotnet.delimiter");
        String cpVersion = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "cpVersion", configStr, "payment.authorizedotnet.cpVersion");
        String cpMarketType = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "cpMarketType", configStr, "payment.authorizedotnet.cpMarketType");
        String cpDeviceType = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "cpDeviceType", configStr, "payment.authorizedotnet.cpDeviceType");
        String method = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "method", configStr, "payment.authorizedotnet.method");
        String emailCustomer = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "emailCustomer", configStr, "payment.authorizedotnet.emailcustomer");
        String emailMerchant = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "emailMerchant", configStr, "payment.authorizedotnet.emailmerchant");
        String testReq = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "testMode", configStr, "payment.authorizedotnet.test");
        String relay = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "relayResponse", configStr, "payment.authorizedotnet.relay");
        String tranKey = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "tranKey", configStr, "payment.authorizedotnet.trankey");
        String login = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "userId", configStr, "payment.authorizedotnet.login");
        String password = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "pwd", configStr, "payment.authorizedotnet.password");
        String transDescription = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "transDescription", configStr, "payment.authorizedotnet.transdescription");
        String duplicateWindow = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "duplicateWindow", configStr, "payment.authorizedotnet.duplicateWindow");        
        if (UtilValidate.isEmpty(ver)) {
            ver = "3.0";
        }
        if (UtilValidate.isEmpty(login)) {
            Debug.logInfo("the login property in " + configStr + " is not configured.", module);
        }
        if (UtilValidate.isEmpty(password) && !("3.1".equals(ver))) {
            Debug.logInfo("The password property in " + configStr + " is not configured.", module);
        }
        if ("3.1".equals(ver)) {
            if (tranKey == null || tranKey.length() <= 0) {
                Debug.logInfo("Trankey property required for version 3.1 reverting to 3.0",module);
                ver = "3.0";
            }
        }
        if (UtilValidate.isNotEmpty(cpMarketType) && UtilValidate.isEmpty(cpVersion)) {
            cpVersion = "1.0";
        }
        
        Properties props = new Properties();
        props.put("url", url);
        props.put("certificateAlias", certificateAlias);
        props.put("ver", ver);
        props.put("delimited", delimited);
        props.put("delimiter", delimiter);
        props.put("method", method);
        props.put("cpVersion", cpVersion);
        props.put("cpMarketType", cpMarketType);
        props.put("cpDeviceType", cpDeviceType);
        props.put("emailCustomer", emailCustomer);
        props.put("emailMerchant", emailMerchant);
        props.put("testReq", testReq);
        props.put("relay", relay);
        props.put("transDescription", transDescription);
        props.put("login", login);
        props.put("password", password);
        props.put("trankey", tranKey);
        props.put("duplicateWindow", duplicateWindow);
        if (cc != null) {
            props.put("cardtype", cc.get("cardType"));
        }
        if (AIMProperties == null) {
            AIMProperties = props;
        }
        if (isTestMode()) {
            Debug.logInfo("Created Authorize.Net properties file: " + props.toString(), module);
        }
        return props;
    }

    private static void buildMerchantInfo(Map<String, Object> params, Properties props, Map<String, Object> AIMRequest) {
        AIMRequest.put("x_Login", props.getProperty("login"));
        String trankey = props.getProperty("trankey");
        if (UtilValidate.isNotEmpty(trankey)) {
            AIMRequest.put("x_Tran_Key", props.getProperty("trankey"));
        } else {
            // only send password if no tran key
            AIMRequest.put("x_Password",props.getProperty("password"));
        }
        
        // api version (non Card Present)
        String apiVersion = props.getProperty("ver");
        if (UtilValidate.isNotEmpty(apiVersion)) {
            AIMRequest.put("x_Version", props.getProperty("ver"));
        }
        
        // CP version
        String cpVersion = props.getProperty("cpver");
        if (UtilValidate.isNotEmpty(cpVersion)) {
            AIMRequest.put("x_cpversion", cpVersion);
        }

        // Check duplicateWindow time frame. If same transaction happens in the predefined time frame then return error. 
        String duplicateWindow = props.getProperty("duplicateWindow");
        if (UtilValidate.isNotEmpty(duplicateWindow)) {
            AIMRequest.put("x_duplicate_window", props.getProperty("duplicateWindow"));
        }
        
        // CP market type
        String cpMarketType = props.getProperty("cpMarketType");
        if (UtilValidate.isNotEmpty(cpMarketType)) {
            AIMRequest.put("x_market_type", cpMarketType);
            
            // CP test mode
            if ("true".equalsIgnoreCase(props.getProperty("testReq"))) {
                AIMRequest.put("x_test_request", props.getProperty("testReq"));                
            }
        }
        
        // CP device typ
        String cpDeviceType = props.getProperty("cpDeviceType");
        if (UtilValidate.isNotEmpty(cpDeviceType)) {
            AIMRequest.put("x_device_type", cpDeviceType);
        }                      
    }

    private static void buildGatewayResponeConfig(Map<String, Object> params, Properties props, Map<String, Object> AIMRequest) {
        if (AIMRequest.get("x_market_type") != null) {
            // card present transaction
            AIMRequest.put("x_response_format", "true".equalsIgnoreCase(props.getProperty("delimited")) ? "1" : "0");            
        } else {
            AIMRequest.put("x_Delim_Data", props.getProperty("delimited"));            
        }
        AIMRequest.put("x_Delim_Char", props.getProperty("delimiter"));
    }

    private static void buildCustomerBillingInfo(Map<String, Object> params, Properties props, Map<String, Object> AIMRequest) {
        try {
            // this would be used in the case of a capture, where one of the parameters is an OrderPaymentPreference
            if (params.get("orderPaymentPreference") != null) {
                GenericValue opp = (GenericValue) params.get("orderPaymentPreference");
                if ("CREDIT_CARD".equals(opp.getString("paymentMethodTypeId"))) {
                    // sometimes the ccAuthCapture interface is used, in which case the creditCard is passed directly
                    GenericValue creditCard = (GenericValue) params.get("creditCard");
                    if (creditCard == null || ! (opp.get("paymentMethodId").equals(creditCard.get("paymentMethodId")))) {
                        creditCard = opp.getRelatedOne("CreditCard");
                    }
                    AIMRequest.put("x_First_Name", UtilFormatOut.checkNull(creditCard.getString("firstNameOnCard")));
                    AIMRequest.put("x_Last_Name", UtilFormatOut.checkNull(creditCard.getString("lastNameOnCard")));
                    AIMRequest.put("x_Company", UtilFormatOut.checkNull(creditCard.getString("companyNameOnCard")));
                    if (UtilValidate.isNotEmpty(creditCard.getString("contactMechId"))) {
                        GenericValue address = creditCard.getRelatedOne("PostalAddress");
                        if (address != null) {
                            AIMRequest.put("x_Address", UtilFormatOut.checkNull(address.getString("address1")));
                            AIMRequest.put("x_City", UtilFormatOut.checkNull(address.getString("city")));
                            AIMRequest.put("x_State", UtilFormatOut.checkNull(address.getString("stateProvinceGeoId")));
                            AIMRequest.put("x_Zip", UtilFormatOut.checkNull(address.getString("postalCode")));
                            AIMRequest.put("x_Country", UtilFormatOut.checkNull(address.getString("countryGeoId")));
                        }
                    }                    
                } else {
                    Debug.logWarning("Payment preference " + opp + " is not a credit card", module);
                }
            } else {
                // this would be the case for an authorization
                GenericValue cp = (GenericValue)params.get("billToParty");
                GenericValue ba = (GenericValue)params.get("billingAddress");
                AIMRequest.put("x_First_Name", UtilFormatOut.checkNull(cp.getString("firstName")));
                AIMRequest.put("x_Last_Name", UtilFormatOut.checkNull(cp.getString("lastName")));
                AIMRequest.put("x_Address", UtilFormatOut.checkNull(ba.getString("address1")));
                AIMRequest.put("x_City", UtilFormatOut.checkNull(ba.getString("city")));
                AIMRequest.put("x_State", UtilFormatOut.checkNull(ba.getString("stateProvinceGeoId")));
                AIMRequest.put("x_Zip", UtilFormatOut.checkNull(ba.getString("postalCode")));
                AIMRequest.put("x_Country", UtilFormatOut.checkNull(ba.getString("countryGeoId")));
            }
            return;
        } catch (GenericEntityException ex) {
            Debug.logError("Cannot build customer information for " + params + " due to error: " + ex.getMessage(), module);
            return;
        }
    }

    private static void buildEmailSettings(Map<String, Object> params, Properties props, Map<String, Object> AIMRequest) {
        GenericValue ea = (GenericValue)params.get("billToEmail");
        AIMRequest.put("x_Email_Customer", props.getProperty("emailCustomer"));
        AIMRequest.put("x_Email_Merchant", props.getProperty("emailMerchant"));
        if (ea != null) {
            AIMRequest.put("x_Email", UtilFormatOut.checkNull(ea.getString("infoString")));
        }
    }

    private static void buildInvoiceInfo(Map<String, Object> params, Properties props, Map<String, Object> AIMRequest) {
        String description = UtilFormatOut.checkNull(props.getProperty("transDescription"));
        String orderId = UtilFormatOut.checkNull((String)params.get("orderId"));
        if (UtilValidate.isEmpty(orderId)) {
            GenericValue orderPaymentPreference = (GenericValue) params.get("orderPaymentPreference");
            if (UtilValidate.isNotEmpty(orderPaymentPreference)) {
                orderId = (String) orderPaymentPreference.get("orderId");
            }
        }
        AIMRequest.put("x_Invoice_Num", "Order " + orderId);
        AIMRequest.put("x_Description", description);
    }

    private static void buildAuthTransaction(Map<String, Object> params, Properties props, Map<String, Object> AIMRequest) {
        GenericValue cc = (GenericValue) params.get("creditCard");
        String currency = (String) params.get("currency");
        String amount = ((BigDecimal)params.get("processAmount")).toString();
        String number = UtilFormatOut.checkNull(cc.getString("cardNumber"));
        String expDate = UtilFormatOut.checkNull(cc.getString("expireDate"));
        String cardSecurityCode = (String) params.get("cardSecurityCode");
        AIMRequest.put("x_Amount", amount);
        AIMRequest.put("x_Currency_Code", currency);        
        AIMRequest.put("x_Method", props.getProperty("method"));
        AIMRequest.put("x_Type", props.getProperty("transType"));
        AIMRequest.put("x_Card_Num", number);
        AIMRequest.put("x_Exp_Date", expDate);
        if (UtilValidate.isNotEmpty(cardSecurityCode)) {
            AIMRequest.put("x_card_code", cardSecurityCode);
        }
        if (AIMRequest.get("x_market_type") != null) {
            AIMRequest.put("x_card_type", getCardType(UtilFormatOut.checkNull(cc.getString("cardType"))));
        }
    }

    private static void buildCaptureTransaction(Map<String, Object> params, Properties props, Map<String, Object> AIMRequest) {
        GenericValue at = (GenericValue) params.get("authTransaction");
        GenericValue cc = (GenericValue) params.get("creditCard");
        String currency = (String) params.get("currency");
        String amount = ((BigDecimal) params.get("captureAmount")).toString();
        String number = UtilFormatOut.checkNull(cc.getString("cardNumber"));
        String expDate = UtilFormatOut.checkNull(cc.getString("expireDate"));
        AIMRequest.put("x_Amount", amount);
        AIMRequest.put("x_Currency_Code", currency);
        AIMRequest.put("x_Method", props.getProperty("method"));
        AIMRequest.put("x_Type", props.getProperty("transType"));
        AIMRequest.put("x_Card_Num", number);
        AIMRequest.put("x_Exp_Date", expDate);
        AIMRequest.put("x_Trans_ID", at.get("referenceNum"));
        AIMRequest.put("x_ref_trans_id", at.get("referenceNum"));
        AIMRequest.put("x_Auth_Code", at.get("gatewayCode"));
        if (AIMRequest.get("x_market_type") != null) {
            AIMRequest.put("x_card_type", getCardType(UtilFormatOut.checkNull(cc.getString("cardType"))));
        }
    }

    private static void buildRefundTransaction(Map<String, Object> params, Properties props, Map<String, Object> AIMRequest) {
        GenericValue at = (GenericValue) params.get("authTransaction");
        GenericValue cc = (GenericValue) params.get("creditCard");
        String currency = (String) params.get("currency");
        String amount = ((BigDecimal) params.get("refundAmount")).toString();
        String number = UtilFormatOut.checkNull(cc.getString("cardNumber"));
        String expDate = UtilFormatOut.checkNull(cc.getString("expireDate"));
        AIMRequest.put("x_Amount", amount);
        AIMRequest.put("x_Currency_Code", currency);
        AIMRequest.put("x_Method", props.getProperty("method"));
        AIMRequest.put("x_Type", props.getProperty("transType"));
        AIMRequest.put("x_Card_Num", number);
        AIMRequest.put("x_Exp_Date", expDate);
        AIMRequest.put("x_Trans_ID", at.get("referenceNum"));
        AIMRequest.put("x_Auth_Code", at.get("gatewayCode"));
        AIMRequest.put("x_ref_trans_id", at.get("referenceNum"));
        if (AIMRequest.get("x_market_type") != null) {
            AIMRequest.put("x_card_type", getCardType(UtilFormatOut.checkNull(cc.getString("cardType"))));
        }
        Debug.logInfo("buildCaptureTransaction. " + at.toString(), module);
    }

    private static void buildVoidTransaction(Map<String, Object> params, Properties props, Map<String, Object> AIMRequest) {
        GenericValue at = (GenericValue) params.get("authTransaction");
        String currency = (String) params.get("currency");
        AIMRequest.put("x_Currency_Code", currency);
        AIMRequest.put("x_Method", props.getProperty("method"));
        AIMRequest.put("x_Type", props.getProperty("transType"));
        AIMRequest.put("x_ref_trans_id", at.get("referenceNum"));
        AIMRequest.put("x_Trans_ID", at.get("referenceNum"));
        AIMRequest.put("x_Auth_Code", at.get("gatewayCode"));
        Debug.logInfo("buildVoidTransaction. " + at.toString(), module);
    }

    private static Map<String, Object> validateRequest(Map<String, Object> params, Properties props, Map<String, Object> AIMRequest) {
        Map<String, Object> result = FastMap.newInstance();
        result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
        return result;
    }

    private static void processAuthTransResult(Map<String, Object> request, Map<String, Object> reply, Map<String, Object> results) {
        AuthorizeResponse ar = (AuthorizeResponse) reply.get("authorizeResponse");
        Boolean authResult = (Boolean) reply.get("authResult");
        results.put("authResult", new Boolean(authResult.booleanValue()));
        results.put("authFlag", ar.getReasonCode());
        results.put("authMessage", ar.getReasonText());
        if (authResult.booleanValue()) { //passed
            results.put("authCode", ar.getAuthorizationCode());
            results.put("authRefNum", ar.getTransactionId());
            results.put("cvCode", ar.getCvResult());
            results.put("avsCode", ar.getAvsResult());
            if (ar.getAmount() == BigDecimal.ZERO) {
                results.put("processAmount", getXAmount(request));
            } else {
                results.put("processAmount", ar.getAmount());
            }
        } else {
            results.put("authCode", ar.getResponseCode());
            results.put("processAmount", BigDecimal.ZERO);
            results.put("authRefNum", AuthorizeResponse.ERROR);
        }
        Debug.logInfo("processAuthTransResult: " + results.toString(),module);
    }

    private static void processCaptureTransResult(Map<String, Object> request, Map<String, Object> reply, Map<String, Object> results) {
        AuthorizeResponse ar = (AuthorizeResponse) reply.get("authorizeResponse");
        Boolean captureResult = (Boolean) reply.get("authResult");
        results.put("captureResult", new Boolean(captureResult.booleanValue()));
        results.put("captureFlag", ar.getReasonCode());
        results.put("captureMessage", ar.getReasonText());
        results.put("captureRefNum", ar.getTransactionId());
        if (captureResult.booleanValue()) { //passed
            results.put("captureCode", ar.getAuthorizationCode());
            if (ar.getAmount() == BigDecimal.ZERO) {
                results.put("captureAmount", getXAmount(request));
            } else {
                results.put("captureAmount", ar.getAmount());
            }
        } else {
            results.put("captureAmount", BigDecimal.ZERO);
        }
        Debug.logInfo("processCaptureTransResult: " + results.toString(),module);
    }

    private static Map<String, Object> processRefundTransResult(Map<String, Object> request, Map<String, Object> reply) {
        Map<String, Object> results = FastMap.newInstance();
        AuthorizeResponse ar = (AuthorizeResponse) reply.get("authorizeResponse");
        Boolean captureResult = (Boolean) reply.get("authResult");
        results.put("refundResult", new Boolean(captureResult.booleanValue()));
        results.put("refundFlag", ar.getReasonCode());
        results.put("refundMessage", ar.getReasonText());
        results.put("refundRefNum", ar.getTransactionId());
        if (captureResult.booleanValue()) { //passed
            results.put("refundCode", ar.getAuthorizationCode());
            if (ar.getAmount() == BigDecimal.ZERO) {
                results.put("refundAmount", getXAmount(request));
            } else {
                results.put("refundAmount", ar.getAmount());
            }
        } else {
            results.put("refundAmount", BigDecimal.ZERO);
        }
        Debug.logInfo("processRefundTransResult: " + results.toString(),module);
        return results;
    }

    private static Map<String, Object> processReleaseTransResult(Map<String, Object> request, Map<String, Object> reply) {
        Map<String, Object> results = FastMap.newInstance();
        AuthorizeResponse ar = (AuthorizeResponse) reply.get("authorizeResponse");
        Boolean captureResult = (Boolean) reply.get("authResult");
        results.put("releaseResult", new Boolean(captureResult.booleanValue()));
        results.put("releaseFlag", ar.getReasonCode());
        results.put("releaseMessage", ar.getReasonText());
        results.put("releaseRefNum", ar.getTransactionId());
        if (captureResult.booleanValue()) { //passed
            results.put("releaseCode", ar.getAuthorizationCode());
            if (ar.getAmount() == BigDecimal.ZERO) {
                results.put("releaseAmount", getXAmount(request));
            } else {
                results.put("releaseAmount", ar.getAmount());
            }
        } else {
            results.put("releaseAmount", BigDecimal.ZERO);
        }
        Debug.logInfo("processReleaseTransResult: " + results.toString(),module);
        return results;
    }

    private static void processAuthCaptureTransResult(Map<String, Object> request, Map<String, Object> reply, Map<String, Object> results) {
        AuthorizeResponse ar = (AuthorizeResponse) reply.get("authorizeResponse");
        Boolean authResult = (Boolean) reply.get("authResult");
        results.put("authResult", new Boolean(authResult.booleanValue()));
        results.put("authFlag", ar.getReasonCode());
        results.put("authMessage", ar.getReasonText());
        results.put("captureResult", new Boolean(authResult.booleanValue()));
        results.put("captureFlag", ar.getReasonCode());
        results.put("captureMessage", ar.getReasonText());
        results.put("captureRefNum", ar.getTransactionId());
        if (authResult.booleanValue()) { //passed
            results.put("authCode", ar.getAuthorizationCode());
            results.put("authRefNum", ar.getTransactionId());
            results.put("cvCode", ar.getCvResult());
            results.put("avsCode", ar.getAvsResult());
            if (ar.getAmount() == BigDecimal.ZERO) {
                results.put("processAmount", getXAmount(request));
            } else {
                results.put("processAmount", ar.getAmount());
            }
        } else {
            results.put("authCode", ar.getResponseCode());
            results.put("processAmount", BigDecimal.ZERO);
            results.put("authRefNum", AuthorizeResponse.ERROR);
        }
        Debug.logInfo("processAuthTransResult: " + results.toString(),module);
    }

    private static String getPaymentGatewayConfigValue(Delegator delegator, String paymentGatewayConfigId, String paymentGatewayConfigParameterName,
                                                       String resource, String parameterName) {
        String returnValue = "";
        if (UtilValidate.isNotEmpty(paymentGatewayConfigId)) {
            try {
                GenericValue payflowPro = delegator.findOne("PaymentGatewayAuthorizeNet", UtilMisc.toMap("paymentGatewayConfigId", paymentGatewayConfigId), false);
                if (UtilValidate.isNotEmpty(payflowPro)) {
                    Object payflowProField = payflowPro.get(paymentGatewayConfigParameterName);
                    if (payflowProField != null) {
                        returnValue = payflowProField.toString().trim();
                    }
                }
            } catch (GenericEntityException e) {
                Debug.logError(e, module);
            }
        } else {
            String value = UtilProperties.getPropertyValue(resource, parameterName);
            if (value != null) {
                returnValue = value.trim();
            }
        }
        return returnValue;
    }
    
    private static String getCardType(String cardType) {
        if ((cardType.equalsIgnoreCase("VISA"))) return "V";
        if ((cardType.equalsIgnoreCase("MASTERCARD"))) return "M";
        if (((cardType.equalsIgnoreCase("AMERICANEXPRESS")) || (cardType.equalsIgnoreCase("AMEX")))) return "A";
        if ((cardType.equalsIgnoreCase("DISCOVER"))) return "D";
        if ((cardType.equalsIgnoreCase("JCB"))) return "J";
        if (((cardType.equalsIgnoreCase("DINERSCLUB")))) return "C";        
        return "";
    }
    
    private static BigDecimal getXAmount(Map<String, Object> request) {
        BigDecimal amt = BigDecimal.ZERO;
        if (request.get("x_Amount") != null) {
            try {
                amt = new BigDecimal((String) request.get("x_Amount"));
            } catch (NumberFormatException e) {
                Debug.logWarning(e, e.getMessage(), module);
            }
        }
        return amt;
    }
}
