package m05bClasses.m05bFirma;

import java.util.Iterator;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;

import m05bClasses.m05bComun;
import m05bClasses.m05bConstantes;
import m05bClasses.m05bFileLog;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class m05bClsFuncionesWS {

	/**
     * Llama al proxy
     * @param method String método del WS al que se invoca
     * @param paramNames String[] con los nombres de los parámetros de la función
     * @param paramValues String[] con los valores de los parámetros de la función
     * @return Object Objeto con el resultado
     * @throws Exception
     */
    public static Object fncLlamarWS(String method, String[] paramNames, String[] paramValues) throws Exception {
    	m05bFileLog miLog = new m05bFileLog();
		miLog.addTraza("", "m05bClsFuncionesWS fncLlamarWS", "FUNCION"+method, m05bConstantes.LOG_NIVEL_BAJO);
		m05bComun miComun = new m05bComun();
		return invoke(miComun.leerPropiedad("firma.urlwsfirma"), method, paramNames,paramValues);
    }//Fin fncLlamarProxy

    public static Object fncLlamarUrlWS(String urlWS, String method, String[] paramNames, String[] paramValues) throws Exception {
    	m05bFileLog miLog = new m05bFileLog();
		miLog.addTraza("", "m05bClsFuncionesWS fncLlamarUrlWS", "Url"+urlWS, m05bConstantes.LOG_NIVEL_BAJO);
		miLog.addTraza("", "m05bClsFuncionesWS fncLlamarUrlWS", "method"+method, m05bConstantes.LOG_NIVEL_BAJO);
        return invoke(urlWS, method, paramNames, paramValues);
    }

    /** Invocar al WS del adaptador genérico de integración */
    /**
     * Metodo que realiza la invocación a un WS
     * @param url String URL de acceso al WS
     * @param method String método del WS al que se invoca
     * @param paramNames String[] con los nombres de los parámetros de la función
     * @param paramValues String[] con los valores de los parámetros de la función
     * @return Object Objeto con el resultado
     * @throws Exception
     */
	private static String invoke(String url, String method, String[] paramNames, String[] paramValues) {
		String rtdo = "";
		try {
			MessageFactory mfactory = MessageFactory.newInstance();
			SOAPMessage message = mfactory.createMessage();
			SOAPPart soapPart = message.getSOAPPart();
			SOAPEnvelope envelope = soapPart.getEnvelope();
			SOAPBody body = envelope.getBody();
			Name name = envelope.createName(method, "", "http://www.openuri.org/");
			SOAPBodyElement element = body.addBodyElement(name);
			for (int i = 0; i < paramNames.length && i < paramValues.length; i++) {
				SOAPElement param = element.addChildElement(envelope.createName(paramNames[i]));
				param.addTextNode(paramValues[i]);
			}
			SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance();
			SOAPConnection con = factory.createConnection();
			SOAPMessage response = con.call(message, url);
			rtdo = getResultado(response);
			//p43bClsLog.info("Resultado Invoke =  " + rtdo);
		} catch (Exception e) {
	    	m05bFileLog miLog = new m05bFileLog();
			miLog.addTraza("", "m05bClsFuncionesWS invoke", "ERROR Invoke: invoke"+e.getMessage(), m05bConstantes.LOG_NIVEL_BAJO);
		}

		/* done */
		return rtdo;
	}

	private static String getResultado(SOAPMessage response) throws SOAPException {
		String rtdo = "";
		SOAPBodyElement soapBodyElement = getSOAPBodyElement(response);
		String responseElementName = soapBodyElement.getElementName().toString();
		String resultElementName = responseElementName.replaceAll("Response$", "Result");
		Iterator iterator = soapBodyElement.getChildElements();
		while (iterator.hasNext()) {
			Object objElement = iterator.next();
			if (objElement instanceof SOAPElement) {
        			SOAPElement element = (SOAPElement) objElement;
				String elementName = element.getElementName().toString();
				if (elementName.equals(resultElementName)) {
					rtdo = element.getValue();
					break;
				}
			}
		}

		/* done */
		return rtdo;
	}

	private static SOAPBodyElement getSOAPBodyElement(SOAPMessage response) throws SOAPException {
		SOAPBodyElement rtdo = null;
		Iterator iterator = response.getSOAPPart().getEnvelope().getBody().getChildElements();
		while (iterator.hasNext()) {
			Object oUndefined = iterator.next();
			if (oUndefined instanceof SOAPBodyElement) {
				rtdo = (SOAPBodyElement) oUndefined;
				break;
			}
		}
		/* done */
		return rtdo;
	}

	/**
	* Codifica en Base64 un array de bytes
	* @param decData Datos a codificar
	* @return String con los datos codificados en Base64
	* @throws
	*/
	public static String encode(byte[] decData) {
		String encData;
		BASE64Encoder encoder;
		encoder = new BASE64Encoder();
		encData = encoder.encode(decData);
		return encData;
	}//Fin encode

	/**
	* Codifica en Base64 una cadena de caracteres
	* @param decData Datos a codificar
	* @return String con los datos codificados en Base64
	* @throws
	*/
	public static String encodeString(String decData) {
		return encode(decData.getBytes());
	}//Fin encodeString

	/**
	* Decodifica una cadena de caracteres que se encuentra codificada en formato Base64
	* @param encData Datos a decodificar
	* @return Bytes con los datos decodificados
	* @throws Exception
	*/
	public static byte[] decode(String encData) throws Exception {
		byte[] decData;
		BASE64Decoder decoder;
		decoder = new BASE64Decoder();
		decData = decoder.decodeBuffer(encData);
		return decData;
	}//Fin decode

	/**
	* Decodifica una cadena de caracteres que se encuentra codificada en formato Base64
	* @param encData Datos a decodificar
	* @return String con los datos decodificados
	* @throws Exception
	*/
	public static String decodeToString(String encData) throws Exception {
		String decoded = null;
		decoded = new String(decode(encData));
		return decoded;
	}//Fin decodeToString
}