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

import java.math.BigDecimal;
import java.util.Locale;
import java.util.Map;

import javolution.util.FastMap;

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

import com.paymentech.orbital.sdk.configurator.Configurator;
import com.paymentech.orbital.sdk.interfaces.RequestIF;
import com.paymentech.orbital.sdk.interfaces.ResponseIF;
import com.paymentech.orbital.sdk.interfaces.TransactionProcessorIF;
import com.paymentech.orbital.sdk.request.FieldNotFoundException;
import com.paymentech.orbital.sdk.request.Request;
import com.paymentech.orbital.sdk.transactionProcessor.TransactionException;
import com.paymentech.orbital.sdk.transactionProcessor.TransactionProcessor;
import com.paymentech.orbital.sdk.util.exceptions.InitializationException;

public class OrbitalPaymentServices {

    public static String module = OrbitalPaymentServices.class.getName();
    private static int decimals = UtilNumber.getBigDecimalScale("invoice.decimals");
    private static int rounding = UtilNumber.getBigDecimalRoundingMode("invoice.rounding");
    public final static String resource = "AccountingUiLabels";

    public static String APPROVED = "Approved";
    public static String DECLINED = "Declined";
    public static String ERROR    = "Error";

    public static final String BIN_VALUE = "000002";
    public static TransactionProcessorIF tp = null;
    public static ResponseIF response = null;
    public static RequestIF request = null;

    public static Map<String, Object> ccAuth(DispatchContext ctx, Map<String, Object> context) {
        Delegator delegator = ctx.getDelegator();
        Map<String, Object> results = ServiceUtil.returnSuccess();
        Map<String, Object> props = buildOrbitalProperties(context, delegator);
        props.put("transType", "AUTH_ONLY");
        //Tell the request object which template to use (see RequestIF.java)
        try {
            request = new Request(RequestIF.NEW_ORDER_TRANSACTION);
        } catch (InitializationException e) {
            Debug.logError("Error in request initialization", module);
            e.printStackTrace();
        }
        buildAuthOrAuthCaptureTransaction(context, delegator, props, request, results);
        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;
        }
        initializeTransactionProcessor();
        Map<String, Object> processCardResponseContext = processCard(request);
        // For Debugging Purpose
        printTransResult((ResponseIF) processCardResponseContext.get("processCardResponse"));
        processAuthTransResult(processCardResponseContext, results);
        return results;
    }

    public static Map<String, Object> ccAuthCapture(DispatchContext ctx, Map<String, Object> context) {
        Delegator delegator = ctx.getDelegator();
        Map<String, Object> results = ServiceUtil.returnSuccess();
        Map<String, Object> props = buildOrbitalProperties(context, delegator);
        props.put("transType", "AUTH_CAPTURE");
        //Tell the request object which template to use (see RequestIF.java)
        try {
            request = new Request(RequestIF.NEW_ORDER_TRANSACTION);
        } catch (InitializationException e) {
            Debug.logError("Error in request initialization", module);
            e.printStackTrace();
        }
        buildAuthOrAuthCaptureTransaction(context, delegator, props, request, results);
        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;
        }
        initializeTransactionProcessor();
        Map<String, Object> processCardResponseContext = processCard(request);
        // For Debugging Purpose
        printTransResult((ResponseIF) processCardResponseContext.get("processCardResponse"));
        processAuthCaptureTransResult(processCardResponseContext, results);
        return results;
    }

    public static Map<String, Object> ccCapture(DispatchContext ctx, Map<String, Object> context) {
        Delegator delegator = ctx.getDelegator();
        Map<String, Object> results = ServiceUtil.returnSuccess();
        Map<String, Object> props = buildOrbitalProperties(context, delegator);
        Locale locale = (Locale) context.get("locale");
        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);
        context.put("orderId", orderPaymentPreference.getString("orderId"));

        props.put("transType", "PRIOR_AUTH_CAPTURE");
        //Tell the request object which template to use (see RequestIF.java)
        try {
            request = new Request(RequestIF.MARK_FOR_CAPTURE_TRANSACTION);
        } catch (InitializationException e) {
            Debug.logError("Error in request initialization", module);
            e.printStackTrace();
        }
        buildCaptureTransaction(context, delegator, props, request, results);
        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;
        }
        initializeTransactionProcessor();
        Map<String, Object> processCardResponseContext = processCard(request);
        // For Debugging Purpose
        printTransResult((ResponseIF) processCardResponseContext.get("processCardResponse"));
        processCaptureTransResult(processCardResponseContext, results);
        return results;
    }

    public static Map<String, Object> ccRefund(DispatchContext ctx, Map<String, Object> context) {
        Locale locale = (Locale) context.get("locale");
        Delegator delegator = ctx.getDelegator();
        Map<String, Object> results = ServiceUtil.returnSuccess();
        Map<String, Object> props = buildOrbitalProperties(context, delegator);
        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);
        context.put("orderId", orderPaymentPreference.getString("orderId"));

        //Tell the request object which template to use (see RequestIF.java)
        try {
            request = new Request(RequestIF.NEW_ORDER_TRANSACTION);
        } catch (InitializationException e) {
            Debug.logError("Error in request initialization", module);
            e.printStackTrace();
        }
        buildRefundTransaction(context, props, request, results);
        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;
        }
        initializeTransactionProcessor();
        Map<String, Object> processCardResponseContext = processCard(request);
        // For Debugging Purpose
        printTransResult((ResponseIF) processCardResponseContext.get("processCardResponse"));
        processRefundTransResult(processCardResponseContext, results);
        return results;
    }

    public static Map<String, Object> ccRelease(DispatchContext ctx, Map<String, Object> context) {
        Locale locale = (Locale) context.get("locale");
        Delegator delegator = ctx.getDelegator();
        Map<String, Object> results = ServiceUtil.returnSuccess();
        Map<String, Object> props = buildOrbitalProperties(context, delegator);

        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
        try {
            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, 
                    "AccountingPaymentTransactionAuthorizationNotFoundCannotRelease", locale));
        }
        context.put("authTransaction", authTransaction);
        context.put("orderId", orderPaymentPreference.getString("orderId"));

        //Tell the request object which template to use (see RequestIF.java)
        try {
            request = new Request(RequestIF.REVERSE_TRANSACTION);
        } catch (InitializationException e) {
            Debug.logError("Error in request initialization", module);
            e.printStackTrace();
        }
        buildReleaseTransaction(context, delegator, props, request, results);
        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;
        }
        initializeTransactionProcessor();
        Map<String, Object> processCardResponseContext = processCard(request);
        // For Debugging Purpose
        printTransResult((ResponseIF) processCardResponseContext.get("processCardResponse"));
        processReleaseTransResult(processCardResponseContext, results);
        return results;
    }


    private static Map<String, Object> buildOrbitalProperties(Map<String, Object> context, Delegator delegator) {
        //TODO: Will move this to property file and then will read it from there.
        String configFile = "/applications/accounting/config/linehandler.properties";
        String paymentGatewayConfigId = (String) context.get("paymentGatewayConfigId");
        Map<String, Object> buildConfiguratorContext = FastMap.newInstance();
        try {
            buildConfiguratorContext.put("OrbitalConnectionUsername", getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "username"));
            buildConfiguratorContext.put("OrbitalConnectionPassword", getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "connectionPassword"));
            buildConfiguratorContext.put("merchantId", getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "merchantId"));
            buildConfiguratorContext.put("engine.class", getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "engineClass"));
            buildConfiguratorContext.put("engine.hostname", getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "hostName"));
            buildConfiguratorContext.put("engine.port", getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "port"));
            buildConfiguratorContext.put("engine.hostname.failover", getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "hostNameFailover"));
            buildConfiguratorContext.put("engine.port.failover", getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "portFailover"));
            buildConfiguratorContext.put("engine.connection_timeout_seconds", getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "connectionTimeoutSeconds"));
            buildConfiguratorContext.put("engine.read_timeout_seconds", getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "readTimeoutSeconds"));
            buildConfiguratorContext.put("engine.authorizationURI", getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "authorizationURI"));
            buildConfiguratorContext.put("engine.sdk_version", getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "sdkVersion"));
            buildConfiguratorContext.put("engine.ssl.socketfactory", getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "sslSocketFactory"));
            buildConfiguratorContext.put("Response.response_type", getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "responseType"));
            String configFileLocation = System.getProperty("ofbiz.home") + configFile;
            Configurator config = Configurator.getInstance(configFileLocation);
            buildConfiguratorContext.putAll(config.getConfigurations());
            config.setConfigurations(buildConfiguratorContext);
        } catch (InitializationException e) {
            Debug.logError("Orbital Configurator Initialization Error: " + e.getMessage(), module);
            e.printStackTrace();
        }
        return buildConfiguratorContext;
    }

    private static String getPaymentGatewayConfigValue(Delegator delegator, String paymentGatewayConfigId,
            String paymentGatewayConfigParameterName) {
        String returnValue = "";
        if (UtilValidate.isNotEmpty(paymentGatewayConfigId)) {
            try {
                GenericValue paymentGatewayOrbital = delegator.findOne("PaymentGatewayOrbital", UtilMisc.toMap("paymentGatewayConfigId", paymentGatewayConfigId), false);
                if (UtilValidate.isNotEmpty(paymentGatewayOrbital)) {
                    Object paymentGatewayOrbitalField = paymentGatewayOrbital.get(paymentGatewayConfigParameterName);
                    if (UtilValidate.isNotEmpty(paymentGatewayOrbitalField)) {
                        return returnValue = paymentGatewayOrbitalField.toString().trim();
                    }
                }
            } catch (GenericEntityException e) {
                Debug.logError(e, module);
            }
        }
        return returnValue;
    }

    private static void buildAuthOrAuthCaptureTransaction(Map<String, Object> params, Delegator delegator, Map<String, Object> props, RequestIF request, Map<String, Object> results) {
        GenericValue cc = (GenericValue) params.get("creditCard");
        BigDecimal amount = (BigDecimal) params.get("processAmount");
        String amountValue = amount.setScale(decimals, rounding).movePointRight(2).toPlainString();
        String number = UtilFormatOut.checkNull(cc.getString("cardNumber"));
        String expDate = UtilFormatOut.checkNull(cc.getString("expireDate"));
        expDate = formatExpDateForOrbital(expDate);
        String cardSecurityCode = (String) params.get("cardSecurityCode");
        String orderId = UtilFormatOut.checkNull((String)params.get("orderId"));
        String transType = props.get("transType").toString();
        String messageType = null;
        if ("AUTH_ONLY".equals(transType)) {
            messageType = "A";
        } else if ("AUTH_CAPTURE".equals(transType)) {
            messageType = "AC";
        }
        try {
            request.setFieldValue("IndustryType", "EC");
            request.setFieldValue("MessageType", UtilFormatOut.checkNull(messageType));
            request.setFieldValue("MerchantID", UtilFormatOut.checkNull(props.get("merchantId").toString()));
            request.setFieldValue("BIN", BIN_VALUE);
            request.setFieldValue("OrderID", UtilFormatOut.checkNull(orderId));
            request.setFieldValue("AccountNum", UtilFormatOut.checkNull(number));

            request.setFieldValue("Amount", UtilFormatOut.checkNull(amountValue));
            request.setFieldValue("Exp", UtilFormatOut.checkNull(expDate));
            // AVS Information
            GenericValue creditCard = null;
            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
                     creditCard = (GenericValue) params.get("creditCard");
                    if (creditCard == null || ! (opp.get("paymentMethodId").equals(creditCard.get("paymentMethodId")))) {
                        creditCard = opp.getRelatedOne("CreditCard");
                    }
                }

                request.setFieldValue("AVSname", "Demo Customer");
                if (UtilValidate.isNotEmpty(creditCard.getString("contactMechId"))) {
                    GenericValue address = creditCard.getRelatedOne("PostalAddress");
                    if (address != null) {
                        request.setFieldValue("AVSaddress1", UtilFormatOut.checkNull(address.getString("address1")));
                        request.setFieldValue("AVScity", UtilFormatOut.checkNull(address.getString("city")));
                        request.setFieldValue("AVSstate", UtilFormatOut.checkNull(address.getString("stateProvinceGeoId")));
                        request.setFieldValue("AVSzip", UtilFormatOut.checkNull(address.getString("postalCode")));
                    }
                }
            } else {
                // this would be the case for an authorization
                GenericValue cp = (GenericValue)params.get("billToParty");
                GenericValue ba = (GenericValue)params.get("billingAddress");
                request.setFieldValue("AVSname", UtilFormatOut.checkNull(cp.getString("firstName")) + UtilFormatOut.checkNull(cp.getString("lastName")));
                request.setFieldValue("AVSaddress1", UtilFormatOut.checkNull(ba.getString("address1")));
                request.setFieldValue("AVScity", UtilFormatOut.checkNull(ba.getString("city")));
                request.setFieldValue("AVSstate", UtilFormatOut.checkNull(ba.getString("stateProvinceGeoId")));
                request.setFieldValue("AVSzip", UtilFormatOut.checkNull(ba.getString("postalCode")));
                request.setFieldValue("AVSCountryCode", UtilFormatOut.checkNull(ba.getString("countryGeoId")));
            }
            // Additional Information
            request.setFieldValue("Comments", "This is building of request object");
            String shippingRef = getShippingRefForOrder(orderId, delegator);
            request.setFieldValue("ShippingRef", shippingRef);
            request.setFieldValue("CardSecVal", UtilFormatOut.checkNull(cardSecurityCode));

            //Display the request
            if ("AUTH_ONLY".equals(transType)) {
                Debug.logInfo("\nAuth Request:\n ======== " + request.getXML());
            } else if ("AUTH_CAPTURE".equals(transType)) {
                Debug.logInfo("\nAuth Capture Request:\n ======== " + request.getXML());
            }
            results.put("processAmount", amount);
        } catch (InitializationException ie) {
            Debug.logInfo("Unable to initialize request object", module);
        } catch (FieldNotFoundException fnfe) {
            Debug.logError("Unable to find XML field in template", module);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void buildCaptureTransaction(Map<String, Object> params, Delegator delegator, Map<String, Object> props, RequestIF request, Map<String, Object> results) {
        GenericValue authTransaction = (GenericValue) params.get("authTransaction");
        GenericValue creditCard = (GenericValue) params.get("creditCard");
        BigDecimal amount = (BigDecimal) params.get("captureAmount");
        String amountValue = amount.setScale(decimals, rounding).movePointRight(2).toPlainString();
        String orderId = UtilFormatOut.checkNull((String)params.get("orderId"));
        try {
            //If there were no errors preparing the template, we can now specify the data
            //Basic Auth Fields
            request.setFieldValue("MerchantID", UtilFormatOut.checkNull(props.get("merchantId").toString()));
            request.setFieldValue("BIN", BIN_VALUE);
            request.setFieldValue("TxRefNum", UtilFormatOut.checkNull(authTransaction.get("referenceNum").toString()));
            request.setFieldValue("OrderID", UtilFormatOut.checkNull(orderId));
            request.setFieldValue("Amount", UtilFormatOut.checkNull(amountValue));

            request.setFieldValue("PCDestName", UtilFormatOut.checkNull(creditCard.getString("firstNameOnCard") + creditCard.getString("lastNameOnCard")));
            if (UtilValidate.isNotEmpty(creditCard.getString("contactMechId"))) {
                GenericValue address = creditCard.getRelatedOne("PostalAddress");
                if (address != null) {
                    request.setFieldValue("PCOrderNum", UtilFormatOut.checkNull(orderId));
                    request.setFieldValue("PCDestAddress1", UtilFormatOut.checkNull(address.getString("address1")));
                    request.setFieldValue("PCDestAddress2", UtilFormatOut.checkNull(address.getString("address2")));
                    request.setFieldValue("PCDestCity", UtilFormatOut.checkNull(address.getString("city")));
                    request.setFieldValue("PCDestState", UtilFormatOut.checkNull(address.getString("stateProvinceGeoId")));
                    request.setFieldValue("PCDestZip", UtilFormatOut.checkNull(address.getString("postalCode")));
                }
            }
            //Display the request
            Debug.logInfo("\nCapture Request:\n ======== " + request.getXML());
            results.put("captureAmount", amount);
        } catch (InitializationException ie) {
            Debug.logInfo("Unable to initialize request object", module);
        } catch (FieldNotFoundException fnfe) {
            Debug.logError("Unable to find XML field in template" + fnfe.getMessage(), module);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void buildRefundTransaction(Map<String, Object> params, Map<String, Object> props, RequestIF request, Map<String, Object> results) {
        GenericValue cc = (GenericValue) params.get("creditCard");
        BigDecimal amount = (BigDecimal) params.get("refundAmount");
        String amountValue = amount.setScale(decimals, rounding).movePointRight(2).toPlainString();
        String number = UtilFormatOut.checkNull(cc.getString("cardNumber"));
        String expDate = UtilFormatOut.checkNull(cc.getString("expireDate"));
        expDate = formatExpDateForOrbital(expDate);
        String orderId = UtilFormatOut.checkNull((String)params.get("orderId"));
        try {
            //If there were no errors preparing the template, we can now specify the data
            //Basic Auth Fields
            request.setFieldValue("IndustryType", "EC");
            request.setFieldValue("MessageType", "R");
            request.setFieldValue("MerchantID", UtilFormatOut.checkNull(props.get("merchantId").toString()));
            request.setFieldValue("BIN", BIN_VALUE);
            request.setFieldValue("OrderID", UtilFormatOut.checkNull(orderId));
            request.setFieldValue("AccountNum", UtilFormatOut.checkNull(number));
            request.setFieldValue("Amount", UtilFormatOut.checkNull(amountValue));
            request.setFieldValue("Exp", UtilFormatOut.checkNull(expDate));
            request.setFieldValue("Comments", "This is a credit card refund");

            Debug.logInfo("\nRefund Request:\n ======== " + request.getXML());
            results.put("refundAmount", amount);
        } catch (InitializationException ie) {
            Debug.logInfo("Unable to initialize request object", module);
        } catch (FieldNotFoundException fnfe) {
            Debug.logError("Unable to find XML field in template", module);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void buildReleaseTransaction(Map<String, Object> params, Delegator delegator, Map<String, Object> props, RequestIF request, Map<String, Object> results) {
        BigDecimal amount = (BigDecimal) params.get("releaseAmount");
        GenericValue authTransaction = (GenericValue) params.get("authTransaction");
        String orderId = UtilFormatOut.checkNull((String)params.get("orderId"));
        try {
            //If there were no errors preparing the template, we can now specify the data
            //Basic Auth Fields
            request.setFieldValue("MerchantID", UtilFormatOut.checkNull(props.get("merchantId").toString()));
            request.setFieldValue("BIN", BIN_VALUE);
            request.setFieldValue("TxRefNum", UtilFormatOut.checkNull(authTransaction.get("referenceNum").toString()));
            request.setFieldValue("OrderID", UtilFormatOut.checkNull(orderId));

            //Display the request
            Debug.logInfo("\nRelease Request:\n ======== " + request.getXML());
            results.put("releaseAmount", amount);
        } catch (InitializationException ie) {
            Debug.logInfo("Unable to initialize request object", module);
        } catch (FieldNotFoundException fnfe) {
            Debug.logError("Unable to find XML field in template" + fnfe.getMessage(), module);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private static void initializeTransactionProcessor() {
        //Create a Transaction Processor
        //The Transaction Processor acquires and releases resources and executes transactions.
        //It configures a pool of protocol engines, then uses the pool to execute transactions.
        try {
            tp = new TransactionProcessor();
        } catch (InitializationException iex) {
            Debug.logError("TransactionProcessor failed to initialize" + iex.getMessage(), module);
            iex.printStackTrace();
        }
    }

    private static Map<String, Object> processCard(RequestIF request) {
        Map<String, Object> processCardResult = FastMap.newInstance();
        try {
            response = tp.process(request);
            if (response.isApproved()) {
                processCardResult.put("authResult", Boolean.TRUE);
            } else {
                processCardResult.put("authResult", Boolean.FALSE);
            }
            processCardResult.put("processCardResponse", response);
        } catch (TransactionException tex) {
            Debug.logError("TransactionProcessor failed to initialize" + tex.getMessage(), module);
            tex.printStackTrace();
        }
        processCardResult.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
        return processCardResult;
    }

    private static void processAuthTransResult(Map<String, Object> processCardResponseContext, Map<String, Object> results) {
        ResponseIF response = (ResponseIF) processCardResponseContext.get("processCardResponse");
        Boolean authResult = (Boolean) processCardResponseContext.get("authResult");
        results.put("authResult", new Boolean(authResult.booleanValue()));
        results.put("authFlag", response.getResponseCode());
        results.put("authMessage", response.getMessage());
        if (authResult.booleanValue()) { //passed
            results.put("authCode", response.getAuthCode());
            results.put("authRefNum", response.getTxRefNum());
            results.put("cvCode", UtilFormatOut.checkNull(response.getCVV2RespCode()));
            results.put("avsCode", response.getAVSResponseCode());
            results.put("processAmount", new BigDecimal(results.get("processAmount").toString()));
        } else {
            results.put("authCode", response.getAuthCode());
            results.put("processAmount", BigDecimal.ZERO);
            results.put("authRefNum", OrbitalPaymentServices.ERROR);
        }
        Debug.logInfo("processAuthTransResult: " + results.toString(),module);
    }

    private static void processAuthCaptureTransResult(Map<String, Object> processCardResponseContext, Map<String, Object> results) {
        ResponseIF response = (ResponseIF) processCardResponseContext.get("processCardResponse");
        Boolean authResult = (Boolean) processCardResponseContext.get("authResult");
        results.put("authResult", new Boolean(authResult.booleanValue()));
        results.put("authFlag", response.getResponseCode());
        results.put("authMessage", response.getMessage());
        results.put("captureResult", new Boolean(authResult.booleanValue()));
        results.put("captureFlag", response.getResponseCode());
        results.put("captureMessage", response.getMessage());
        results.put("captureRefNum", response.getTxRefNum());
        if (authResult.booleanValue()) { //passed
            results.put("authCode", response.getAuthCode());
            results.put("authRefNum", response.getTxRefNum());
            results.put("cvCode", UtilFormatOut.checkNull(response.getCVV2RespCode()));
            results.put("avsCode", response.getAVSResponseCode());
            results.put("processAmount", new BigDecimal(results.get("processAmount").toString()));
        } else {
            results.put("authCode", response.getAuthCode());
            results.put("processAmount", BigDecimal.ZERO);
            results.put("authRefNum", OrbitalPaymentServices.ERROR);
        }
        Debug.logInfo("processAuthCaptureTransResult: " + results.toString(),module);
    }

    private static void processCaptureTransResult(Map<String, Object> processCardResponseContext, Map<String, Object> results) {
        ResponseIF response = (ResponseIF) processCardResponseContext.get("processCardResponse");
        Boolean captureResult = (Boolean) processCardResponseContext.get("authResult");
        results.put("captureResult", new Boolean(captureResult.booleanValue()));
        results.put("captureFlag", response.getResponseCode());
        results.put("captureMessage", response.getMessage());
        results.put("captureRefNum", response.getTxRefNum());
        if (captureResult.booleanValue()) { //passed
            results.put("captureCode", response.getAuthCode());
            results.put("captureAmount", new BigDecimal(results.get("captureAmount").toString()));
        } else {
            results.put("captureAmount", BigDecimal.ZERO);
        }
        Debug.logInfo("processCaptureTransResult: " + results.toString(),module);
    }

    private static void processRefundTransResult(Map<String, Object> processCardResponseContext, Map<String, Object> results) {
        ResponseIF response = (ResponseIF) processCardResponseContext.get("processCardResponse");
        Boolean refundResult = (Boolean) processCardResponseContext.get("authResult");
        results.put("refundResult", new Boolean(refundResult.booleanValue()));
        results.put("refundFlag", response.getResponseCode());
        results.put("refundMessage", response.getMessage());
        results.put("refundRefNum", response.getTxRefNum());
        if (refundResult.booleanValue()) { //passed
            results.put("refundCode", response.getAuthCode());
            results.put("refundAmount", new BigDecimal(results.get("refundAmount").toString()));
        } else {
            results.put("refundAmount", BigDecimal.ZERO);
        }
        Debug.logInfo("processRefundTransResult: " + results.toString(),module);
    }

    private static void processReleaseTransResult(Map<String, Object> processCardResponseContext, Map<String, Object> results) {
        ResponseIF response = (ResponseIF) processCardResponseContext.get("processCardResponse");
        Boolean releaseResult = (Boolean) processCardResponseContext.get("authResult");
        results.put("releaseResult", new Boolean(releaseResult.booleanValue()));
        results.put("releaseFlag", response.getResponseCode());
        results.put("releaseMessage", response.getMessage());
        results.put("releaseRefNum", response.getTxRefNum());
        if (releaseResult.booleanValue()) { //passed
            results.put("releaseCode", response.getAuthCode());
            results.put("releaseAmount", new BigDecimal(results.get("releaseAmount").toString()));
        } else {
            results.put("releaseAmount", BigDecimal.ZERO);
        }
        Debug.logInfo("processReleaseTransResult: " + results.toString(),module);
    }

    private static void printTransResult(ResponseIF response) {
        Map<String, Object> generatedResponse = FastMap.newInstance();
        generatedResponse.put("isGood",  response.isGood());
        generatedResponse.put("isError", response.isError());
        generatedResponse.put("isQuickResponse",  response.isQuickResponse());
        generatedResponse.put("isApproved", response.isApproved());
        generatedResponse.put("isDeclined",  response.isDeclined());
        generatedResponse.put("AuthCode",  response.getAuthCode());
        generatedResponse.put("TxRefNum",  response.getTxRefNum());
        generatedResponse.put("ResponseCode",  response.getResponseCode());
        generatedResponse.put("Status",  response.getStatus());
        generatedResponse.put("Message",  response.getMessage());
        generatedResponse.put("AVSCode",  response.getAVSResponseCode());
        generatedResponse.put("CVV2ResponseCode", response.getCVV2RespCode());

        Debug.logInfo("printTransResult === " + generatedResponse.toString(),module);
    }

    private static String formatExpDateForOrbital(String expDate) {
        String formatedDate = expDate.substring(0, 2) + expDate.substring(5);
        return formatedDate;
    }

    private static String getShippingRefForOrder(String orderId, Delegator delegator) {
        String shippingRef = "";
        try {
            GenericValue orderHeader = delegator.findOne("OrderHeader", false, UtilMisc.toMap("orderId", orderId));
            GenericValue trackingCodeOrder = EntityUtil.getFirst(orderHeader.getRelated("TrackingCodeOrder"));
            GenericValue trackingCode = null;
            if (UtilValidate.isNotEmpty(trackingCodeOrder)) {
                trackingCode = trackingCodeOrder.getRelatedOne("TrackingCode");
            }
            if (UtilValidate.isNotEmpty(trackingCode) && UtilValidate.isNotEmpty(trackingCode.getString("description"))) {
                // get tracking code description and provide it into shipping reference.
                shippingRef = trackingCode.getString("trackingCodeId") + "====" + trackingCode.getString("description");
            } else {
                shippingRef = "No Tracking Info processed in order";
            }
        } catch (GenericEntityException e) {
            Debug.logError("Shipping Ref not found returning empty string", module);
            e.printStackTrace();
        }
        return shippingRef;
    }

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