/**
 * 
 */


package gov.va.med.cds.hapi.extension;


import java.io.IOException;
import java.io.StringWriter;
import java.util.HashSet;
import java.util.Set;

import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import org.w3c.dom.Document;

import ca.uhn.hl7v2.ErrorCode;
import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.model.GenericMessage;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.parser.DefaultXMLParser;
import ca.uhn.hl7v2.parser.ModelClassFactory;


/**
 * @author vhaislegberb
 * 
 */
public class CustomUnformattedXmlParser
    extends
        DefaultXMLParser
{
    public CustomUnformattedXmlParser( )
    {
        this( new CustomCdsModelClassFactory() );
    }


    public CustomUnformattedXmlParser( ModelClassFactory modelClassFactory )
    {
    	super( new CdsHapiContext(modelClassFactory));
    }

    @Override
    protected String doEncode( Message source )
        throws HL7Exception
    {
        if ( source instanceof GenericMessage )
            throw new HL7Exception( "Can't XML-encode a GenericMessage.  Message must have a recognized structure." );
        Document doc = encodeDocument( source );
        doc.getDocumentElement().setAttribute( "xmlns", "urn:hl7-org:v2xml" );
        StringWriter out = new StringWriter();
        OutputFormat outputFormat = new OutputFormat( "", null, false );
        outputFormat.setPreserveSpace( true );
        XMLSerializer ser = new XMLSerializer( out, outputFormat );  
        //setKeepAsOriginalNodes( new String[] { "OBX.5", "RXE.21" } );
        Set<String> nodes = new HashSet<String>(); 
        nodes.add("OBX.5");
        nodes.add("RXE.21");
        getParserConfiguration().setXmlDisableWhitespaceTrimmingOnNodeNames( nodes );
        try
        {
            ser.serialize( doc );
        }
        catch ( IOException e )
        {
            throw new HL7Exception( "IOException serializing XML document to string", ErrorCode.APPLICATION_INTERNAL_ERROR, e );
        }
        return out.toString();
    }


    public String getEncoding( String message )
    {
        String encoding = null;

        // check for a number of expected strings
        String[] expected = { "<BHS", "<MSH.1", "<MSH.2", "</MSH>" };
        boolean isXML = true;
        for ( int i = 0; i < expected.length; i++ )
        {
            if ( message.indexOf( expected[i] ) < 0 )
            {
                isXML = true;
                break;
            }
            isXML = false;
        }
        if ( isXML )
            encoding = "XML";

        return encoding;
    }


    public String getVersion( String message )
        throws HL7Exception
    {

        if ( message.contains( "<BHS" ) )
        {
            return "2.4";
        }

        return super.getVersion( message );
    }
}
