package cat.cert;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Properties;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.ws.security.util.Base64;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import x0CoreSchema.oasisNamesTcDss1.VerifyResponseDocument;
import x0CoreSchema.oasisNamesTcDss1.OptionalOutputsDocument.OptionalOutputs;
import x0CoreSchema.oasisNamesTcDss1.ProcessingDetailsDocument.ProcessingDetails;
import x0ProfilesXSS.oasisNamesTcDss1.X509CertificateInfoDocument.X509CertificateInfo;
public class Utils {

	public static void setProxyConfiguration() {
		Properties props = System.getProperties(); 

		props.put("proxyHost","192.168.1.25");
		props.put("proxyPort","8080");

		System.setProperties(props);
	}

	public static byte[] decodeBase64String(final String content) throws Exception {
		return Base64.decode(content);
	}

	public static String readFile(final String filename) throws Exception {
		StringBuilder sb = new StringBuilder();

		ClassLoader cl = Thread.currentThread().getContextClassLoader();
		InputStream is = cl.getResourceAsStream(filename);
		DataInputStream dis = new DataInputStream(is);
		
		byte[] buffer = new byte[4096];
		for (int len; (len = dis.read(buffer)) > 0;) {
			sb.append(new String(buffer, 0, len));
		}
		dis.close();

		return sb.toString();
	}

	public static byte[] readBase64File(final String filename) throws Exception {
		return (decodeBase64String(readFile(filename)));
	}

	public static byte[] readBase64String(final String b64) throws Exception {
		return (decodeBase64String(b64));
	}

	public static String readXmlFile(final String filename) throws Exception {
		return readFile(filename);
	}

	/**
	 * Builds a certificate from the path of the file that contains it.
	 * @param path path of the file that contains the certificate
	 * @return java.security.X509Certificate
	 * @throws CertificateException
	 */
	public static X509Certificate getCertificate(String path) throws CertificateException {
		InputStream stream = ClassLoader.getSystemResourceAsStream(path);
		return (X509Certificate)CertificateFactory.getInstance(
		"X.509").generateCertificate(stream);
	}

	/** 
	 * Returns the contents of the file in a byte array.
	 */
	public static byte[] getBytesFromFile(String path) throws IOException {

		InputStream is = ClassLoader.getSystemResourceAsStream(path);
		byte[] bytes = getBytes(is);
		is.close();

		return bytes;
	}


	/**
	 * Gets a byte array from an InputStream.
	 * @param is InputStream
	 * @return byte[]
	 * @throws IOException
	 */
	public static byte[] getBytes(InputStream is) throws IOException {

		ByteArrayOutputStream baos = new ByteArrayOutputStream();

		int bytee;
		while (-1!=(bytee=is.read()))
		{
			baos.write(bytee);
		}
		baos.close();
		byte[] bytes = baos.toByteArray();

		is.close();
		return bytes;
	}

	public static void writeFile (Document doc, String fileName) {

		try {
			TransformerFactory transformerFactory = TransformerFactory.newInstance();
			Transformer transformer = transformerFactory.newTransformer();
			transformer.setOutputProperty(OutputKeys.METHOD, "xml");
			transformer.transform(new DOMSource(doc), new StreamResult(new File(fileName)));

		} catch (TransformerException spe) {
			// I/O error
			spe.printStackTrace();
		}

	} //fi writeFile

	public static  void obrirSOAP(PrintStream pos){
		pos.print("<?xml version=\"1.0\" encoding=\"latin1\"?>");
//		pos.print("<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">");
//		pos.print("<SOAP-ENV:Body>");


	}

	public static  void tancarSOAP(PrintStream pos){
//		pos.print("</SOAP-ENV:Body>");
//		pos.print("</SOAP-ENV:Envelope>");



	}



	public static Document parseXML (String fileName) {

		Document document = null;

		/* Si el fitxer d'entrada no existeix, acabar el procés */
		File fitxer_entrada= new File(fileName);
		if (!fitxer_entrada.exists()) {
			System.out.println ("\n\nEl fitxer " + fitxer_entrada + " no existeix. No es pot continuar el proces");
			System.exit(1);
		}

		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			document = builder.parse(fitxer_entrada);

		} catch (SAXParseException spe) {
			// Error generated by the parser
			System.out.println("\n** Parsing error" + ", line " +
					spe.getLineNumber() + ", uri " + spe.getSystemId());
			System.out.println("   " + spe.getMessage());

			// Use the contained exception, if any
			Exception x = spe;

			if (spe.getException() != null) {
				x = spe.getException();
			}

			x.printStackTrace();
		} catch (SAXException sxe) {
			// Error generated during parsing)
			Exception x = sxe;

			if (sxe.getException() != null) {
				x = sxe.getException();
			}

			x.printStackTrace();
		} catch (ParserConfigurationException pce) {
			// Parser with specified options can't be built
			pce.printStackTrace();
		} catch (IOException ioe) {
			// I/O error
			ioe.printStackTrace();
		}

		return document;

	} // fi readFile


	public static Document stringToXML (String encData) {

		Document document = null;

		/* Si el fitxer d'entrada no existeix, acabar el procés */

		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			ByteArrayInputStream bais = new ByteArrayInputStream(encData.getBytes());
			document = builder.parse(bais);

		} catch (SAXParseException spe) {
			// Error generated by the parser
			System.out.println("\n** Parsing error" + ", line " +
					spe.getLineNumber() + ", uri " + spe.getSystemId());
			System.out.println("   " + spe.getMessage());

			// Use the contained exception, if any
			Exception x = spe;

			if (spe.getException() != null) {
				x = spe.getException();
			}

			x.printStackTrace();
		} catch (SAXException sxe) {
			// Error generated during parsing)
			Exception x = sxe;

			if (sxe.getException() != null) {
				x = sxe.getException();
			}

			x.printStackTrace();
		} catch (ParserConfigurationException pce) {
			// Parser with specified options can't be built
			pce.printStackTrace();
		} catch (IOException ioe) {
			// I/O error
			ioe.printStackTrace();
		}

		return document;

	} // fi readString

	public static void writeXMLtofile (Document doc, String fileName) {

		try {
			TransformerFactory transformerFactory = TransformerFactory.newInstance();
			Transformer transformer = transformerFactory.newTransformer();
			transformer.setOutputProperty(OutputKeys.METHOD, "xml");
			transformer.transform(new DOMSource(doc), new StreamResult(new File(fileName)));

		} catch (TransformerException spe) {
			// I/O error
			spe.printStackTrace();
		}

	} //fi writeFile

	public static VerifyResponseDocument capturaVerify (String filePath) throws XmlException, IOException{

		FileInputStream resposta = new FileInputStream(filePath);
		VerifyResponseDocument verifResp = (VerifyResponseDocument)XmlObject.Factory.parse(resposta);

		return verifResp;

	}

	public static Object[] inicialitza (Object[] object){

		for (int i=0;i<object.length;i++)
			object[i]=null;

		return object;
	}


	public static ProcessingDetails[] getProcessingDetails (VerifyResponseDocument verifyResp){

		ProcessingDetails[] processingDetails = null;
		OptionalOutputs optOutputs = verifyResp.getVerifyResponse().getOptionalOutputs();
		if(verifyResp.getVerifyResponse().getOptionalOutputs()!=null){
			processingDetails = optOutputs.getProcessingDetailsArray();
		}

		return processingDetails;
	}


	public static X509CertificateInfo[] getX509 (VerifyResponseDocument verifyResp){

		X509CertificateInfo[] x509CertificateInfo = new X509CertificateInfo[1];
		x509CertificateInfo[0]=null;

		OptionalOutputs optOutputs = verifyResp.getVerifyResponse().getOptionalOutputs();
		if(verifyResp.getVerifyResponse().getOptionalOutputs()!=null){
			x509CertificateInfo = optOutputs.getX509CertificateInfoArray();
		}

		return x509CertificateInfo;
	}


	public static HashMap<String,String> getAttributes (X509CertificateInfo x509CertificateInfo){

		NodeList attributesList = x509CertificateInfo.getDomNode().getChildNodes();  
		HashMap<String,String> atts = new HashMap<String,String>();

		for (int a=0;a<attributesList.getLength();a++){
			String attributeName;
			String attributeValue;
			Element attribute;

			attribute = ((Element)attributesList.item(a));
			attributeName = attribute.getAttribute("Name");
			if (attribute.getChildNodes().item(0)!=null)
				attributeValue = attribute.getChildNodes().item(0).getChildNodes().item(0).getNodeValue();
			else attributeValue="";           				

			atts.put(attributeName, attributeValue);
		}

		return atts;

	}


	public static String getOutPath (){


		Calendar calendar = Calendar.getInstance();
		calendar.get(Calendar.DAY_OF_MONTH);
		calendar.get(Calendar.DAY_OF_MONTH);
		calendar.get(Calendar.DAY_OF_MONTH);
		calendar.get(Calendar.DAY_OF_MONTH);


		Integer year = calendar.get(Calendar.YEAR);
		Integer month = calendar.get(Calendar.MONTH);
		month++;
		Integer day = calendar.get(Calendar.DAY_OF_MONTH);
		Integer hour = calendar.get(Calendar.HOUR_OF_DAY);
		Integer minutes = calendar.get(Calendar.MINUTE);

		String date = year.toString()+month.toString()+day.toString()+"_"+hour+"h"+minutes+"m";

		return date;

	}


}



