
package gov.va.med.pharmacy.utility;


import java.io.InputStream;
import java.util.ArrayList;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.resource.ResourceException;

import gov.va.med.exception.FoundationsException;
import gov.va.med.vistalink.adapter.cci.VistaLinkAppProxyConnectionSpec;
import gov.va.med.vistalink.adapter.cci.VistaLinkConnection;
import gov.va.med.vistalink.adapter.cci.VistaLinkConnectionFactory;
import gov.va.med.vistalink.adapter.cci.VistaLinkConnectionSpec;
import gov.va.med.vistalink.institution.InstitutionMappingDelegate;
import gov.va.med.vistalink.rpc.RpcRequest;
import gov.va.med.vistalink.rpc.RpcRequestFactory;
import gov.va.med.vistalink.rpc.RpcResponse;


/**
 * This class provides VistA connectivity. It uses VistALink to execute RPC's on the remote VistA and retrieve the results.
 */
public class VistaLinkConnectionUtility  {

	// TO-DO
    //private static final org.apache.logging.log4j.Logger LOG = org.apache.logging.log4j.LogManager.getLogger(VistaLinkConnectionUtility.class);

    private static final String DUZ_CONNECTION_SPEC = "DUZ";
    private static final String VPID_CONNECTION_SPEC = "VPID";
    private static final String APP_PROXY_CONNECTION_SPEC = "APP PROXY";
    public static final int DEFAULT_RPCTIMEOUT = 60000;
   
    public static final String DEFAULT_CONNSPEC = "DUZ";
    
    
    /**
     * Executes an RPC call on the VistA.
     * @param division TODO
     * @param rpcContext The context this RPC will be called in.
     * @param rpcName The name of the RPC.
     * @param rpcParams Parameter(s) that will be passed to the VistA.
     * @param user The user making the RPC call. If the user is null, default user will be used.
     * 
     * @return The RpcResponse.
     * @throws Exception 
     */
    public RpcResponse sendRequest(String division, String rpcContext, String rpcName, ArrayList<Object> rpcParams) throws Exception {

       // LOG.debug("VistA request [" + rpcContext + ", " + rpcName + "] with parameters: " + rpcParams);

    	
        String proxyUser ="PSOAPPLICATIONPROXY,PSO";
    	
        VistaLinkConnection connection = null;

        try {
        	
        	
        	Properties properties = new Properties();
    		
    		InputStream inputStream = null;
    		try{
    			
    			inputStream = this.getClass().getClassLoader().getResourceAsStream("gov.va.med.pharmacy.vistalink.properties");

    			if(null!=inputStream){
    				properties.load(inputStream);    				
    				proxyUser = properties.getProperty("vistalink.proxyuser").trim();
    			}
    			
    		} finally {
    			if (null != inputStream) {
    				StreamUtilities.safeClose(inputStream);
    			}
    		}
    		
    		connection = getConnection(division, proxyUser);
        	
            RpcRequest rpcRequest = RpcRequestFactory.getRpcRequest();

            rpcRequest.setRpcContext(rpcContext);
            rpcRequest.setRpcName(rpcName);
            rpcRequest.setRpcClientTimeOut(DEFAULT_RPCTIMEOUT);
            rpcRequest.setUseProprietaryMessageFormat(true);
			
            if (rpcParams != null) 
			{
				rpcRequest.setParams(rpcParams);
				
				//System.out.println("-- rpcParams--: "+rpcParams.toString());
			} 
            
            RpcResponse response = connection.executeRPC(rpcRequest);

            //LOG.debug("VistA response [" + rpcContext + ", " + rpcName + "]: " + response.getResults());

            return response;
        } catch (FoundationsException e) {
        	throw new Exception (e);
        } finally {
            if (connection != null) {
                try {
                    connection.close();
                } catch (ResourceException e) {
                    //LOG.error("Error closing VistALink connection.", e);
                	e.printStackTrace();
                }
            }
        }
    }

    /**
     * Retrieves VistALink connection.
     * 
     * @return A VistaLinkConnection.
     * @throws Exception 
     */
    private VistaLinkConnection getConnection(String division, String proxyUser) throws Exception {

       // LOG.debug("Connecting to VistAlink as: " + userId + ", " + division);

        Context ic = null;

        try {
            VistaLinkConnectionSpec connectionSpec = null;

            connectionSpec = new VistaLinkAppProxyConnectionSpec(division, proxyUser);
            
            ic = new InitialContext();
            String jndiName = InstitutionMappingDelegate.getJndiConnectorNameForInstitution(division);
            VistaLinkConnectionFactory cf = (VistaLinkConnectionFactory) ic.lookup(jndiName);
            VistaLinkConnection connection = (VistaLinkConnection) cf.getConnection(connectionSpec);

            return connection;
       
        }
        
        catch (Exception e) {
            // LOG.error("VistALink error while retrieving connection.", e);
            //throw new InterfaceException(e, InterfaceException.INTERFACE_ERROR, InterfaceException.PRE_ENCAPSULATION);
        	throw new Exception (e);
        } finally {
        	if (ic != null){
           ic.close();
        	};
        }
    }
}
