package gov.va.med.esr.common.util;

import org.apache.commons.io.IOUtils;
import org.apache.cxf.headers.Header;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.io.CacheAndWriteOutputStream;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.io.CachedOutputStreamCallback;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.message.Attachment;
import org.apache.cxf.message.Message;


import javax.xml.namespace.QName;


import weblogic.xml.security.wsse.Security;

import java.io.File;
import java.io.FileWriter;
import java.io.OutputStream;
import java.io.StringWriter;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;


/**
 * @author DNS   faulkj
 * Utility for logging ACA IRS business headers and payloads sent by outbound CXF services
 * Intended ONLY for development use
 */
public class CxfOutInterceptor extends LoggingOutInterceptor  {

	public CxfOutInterceptor() {
        super(Phase.PRE_STREAM);
    }

	String soapXml = "";
	StringBuilder builder = new StringBuilder();


	 @Override
    public void handleMessage(Message message) throws Fault {
        this.setPrettyLogging(true);
        this.setShowBinaryContent(true);
        this.setShowMultipartContent(true);

		OutputStream out = message.getContent(OutputStream.class);
        final CacheAndWriteOutputStream newOut = new CacheAndWriteOutputStream(out);
        message.setContent(OutputStream.class, newOut);
        getHeader(message, builder);
        getAttach(message, builder);
        newOut.registerCallback(new LoggingCallback());

    }

    public class LoggingCallback implements CachedOutputStreamCallback {
        public void onFlush(CachedOutputStream cos) {
        }

        public void onClose(CachedOutputStream cos) {
            try {

                cos.writeCacheTo(builder, limit);
                String soapXml = builder.toString();

                FileWriter f = null;
                try {
	                    f = new FileWriter (new File("cxf.intercept.txt"));

	                    f.append(soapXml);

                    } catch (Exception ex) {

                    } finally {
                    	if (f != null) {
                    		IOUtils.closeQuietly(f);
                    	}
                    }

            } catch (Exception e) {
            }

        }
	}


 @SuppressWarnings("unchecked")
protected String getHeader(Message message, StringBuilder builder) {
     List<Header> headers = (List<Header>) message.get(Header.HEADER_LIST);


     /*if(headers != null) {
         for(Header header:headers) {

        	 //Manifest header
        	 if(header.getName().getLocalPart().equalsIgnoreCase(ACATrnsmtManifestReqDtlType.class.getName())) {

               String m = this.buildXmlDocument(new JAXBElement(new QName(ACATrnsmtManifestReqDtlType.class.getSimpleName()),
            		   ACATrnsmtManifestReqDtlType.class, header.getObject()));

               builder.append(m);
             }

             //Business Header
             if(header.getName().getLocalPart().equalsIgnoreCase(ACABulkBusinessHeaderRequestType.class.getName())) {

               String m = this.buildXmlDocument(new JAXBElement(new QName(ACABulkBusinessHeaderRequestType.class.getSimpleName()),
            		   ACABulkBusinessHeaderRequestType.class, header.getObject()));

               builder.append(m);
             }

             //WSSESecurity
             if(header.getName().getLocalPart().equalsIgnoreCase(Security.class.getName())) {

               String m = this.buildXmlDocument(new JAXBElement(new QName(Security.class.getSimpleName()),
            		   Security.class, header.getObject()));

               builder.append(m);
             }





             //}
         }
     } else {
    	 builder.append("HEADERS ARE NULL");
     }*/

     return null;
 }

 protected String getAttach(Message message, StringBuilder builder) {

     try {
         Collection<Attachment> att = message.getAttachments();
         if (att != null) {
             Iterator it = att.iterator();

             while (it.hasNext()) {
            	 Object o = it.next();
            	 builder.append(o.toString());

             }
         }
     } catch (Exception ex) {
    	 //System.out.println("Exception logging the attachments:" + ex.getMessage());
     }



     return null;
     //**************end*****************
 }

 private String buildXmlDocument(JAXBElement document) {

	  Class<?> clazz = document.getValue().getClass();
	  try {
	    JAXBContext context =
	        JAXBContext.newInstance(clazz.getPackage().getName());
	    Marshaller m = context.createMarshaller();
	    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
	    StringWriter sw = new StringWriter();
	    m.marshal(document, sw);
	    String xml = sw.toString();

	    return xml;

	  } catch (JAXBException e) {
		  //System.out.println("jax b err: " + e);

	  }
	  return null;
}



}