/*
 * NIST
 * Hl7GazelleClient.java Feb 19, 2008
 *
 * This code was produced by the National Institute of Standards and
 * Technology (NIST). See the "nist.disclaimer" file given in the distribution
 * for information on the use and redistribution of this software.
 */

package gov.nist.hl7.ws.client.messagevalidation;

import gov.nist.hl7.ws.repository.RepositoryRepositorySOAP12Port_httpStub;
import gov.nist.hl7.ws.repository.RepositoryRepositorySOAP12Port_httpStub.Bind;
import gov.nist.hl7.ws.repository.RepositoryRepositorySOAP12Port_httpStub.GetProfile;
import gov.nist.hl7.ws.repository.RepositoryRepositorySOAP12Port_httpStub.LoadProfile;
import gov.nist.hl7.ws.repository.RepositoryRepositorySOAP12Port_httpStub.LoadResource;
import gov.nist.hl7.ws.messagevalidation.Hl7GazelleMessageValidationHl7GazelleMessageValidationSOAP12Port_httpStub;
import gov.nist.hl7.ws.messagevalidation.Hl7GazelleMessageValidationHl7GazelleMessageValidationSOAP12Port_httpStub.GetDetailedResults;
import gov.nist.hl7.ws.messagevalidation.Hl7GazelleMessageValidationHl7GazelleMessageValidationSOAP12Port_httpStub.GetSummaryResults;
import gov.nist.hl7.ws.messagevalidation.Hl7GazelleMessageValidationHl7GazelleMessageValidationSOAP12Port_httpStub.ValidateMessage;

import java.io.File;
import java.io.IOException;
import java.rmi.RemoteException;

import org.apache.axis2.client.Options;
import org.apache.xmlbeans.XmlException;

import net.ihe.hl7.ws.overviewresults.ReferencedStandardDocument;
import net.ihe.hl7.ws.overviewresults.ReferencedStandardDocument.ReferencedStandard;
import net.ihe.hl7.ws.xmlmessagedata.MessageMetaDataDocument;
import net.ihe.hl7.ws.xmlmessagedata.MessageMetaDataType;
import net.ihe.hl7.ws.xmlvalidationcontext.NISTHL7V2ValidationContextDefinitionDocument;
import net.ihe.hl7.ws.xmlvalidationcontext.ValidationContextDocument;
import net.ihe.hl7.ws.xmlvalidationcontext.ValidationContextType;

/**
 * @author Roch Bertucat (NIST)
 *
 */
public final class Hl7GazelleClient {

   private static final String URL = "http://localhost:8080/NISTHl7WS/services/";
   // private static final String URL = "http://xreg2.nist.gov:8080/HL7WS/services/";
    private static Hl7GazelleMessageValidationHl7GazelleMessageValidationSOAP12Port_httpStub mvStub;
    private static RepositoryRepositorySOAP12Port_httpStub rStub;

    private Hl7GazelleClient() {

    }

    /**
     *
     * @param args
     * @throws Exception
     */
    public static void main(final String[] args) throws Exception {
        // Create the client instance
        mvStub = new Hl7GazelleMessageValidationHl7GazelleMessageValidationSOAP12Port_httpStub(URL + "Hl7GazelleMessageValidation");
        rStub =  new RepositoryRepositorySOAP12Port_httpStub(URL + "Repository");

        // Set the timeout for 60 minutes (for large files)
        Options options = mvStub._getServiceClient().getOptions();
        options.setTimeOutInMilliSeconds(600000);
        options = rStub._getServiceClient().getOptions();
        options.setTimeOutInMilliSeconds(600000);

        // startCase1();
        startCase2();
    }

    /**
     * Case overview:
     * -------------
     * - Use a profile from the repository
     * - Validate and display
     * @throws Exception
     */
    private static void startCase2() throws Exception {

        // should be an OUL_R22 profile
        String oid = "1.2.814.99999.1.1";

        // Check if the profile with the OID exists
        GetProfile getProf = new GetProfile();
        getProf.setOid(oid);
        String profile = rStub.getProfile(getProf).get_return();
        if (profile.equals("")) {
            throw new Exception("Profile not available.");
        }

        // Load NIST HL7 message context
        String xmlValidationContext = getValidationContext(new File("files/MVCCheckComponent.xml"));

        // Build the Gazelle XML Reference Standard file
        String xmlReferenceStandard = getReferenceStandard();

        // Build the Gazelle Message MetaData file
        String xmlMetaData = getMetaData("English", oid);

        // Set the message to be validated
        String message = Utils.getContents(new File("files/9.2.3.5.hl7"));

        // Check the status of the service
        String xmlValidationServiceStatus =
            mvStub.getValidationServiceStatus().get_return();
        System.out.println(xmlValidationServiceStatus);

        if (!xmlValidationServiceStatus.equals("OK")) {
            throw new Exception("Service Status.");
        }

        // Set the Gazelle objectGUID
        String objectGUID1 = "12334-8942";

        validateAndDisplay(objectGUID1, xmlReferenceStandard, xmlValidationContext,
                xmlMetaData, message);

    }

    /**
     * Case overview:
     * -------------
     * - Load the profile into the repository
     * - Load the resource into the repository
     * - Bind them
     * - Validate and display
     * @throws Exception
     */
    private static void startCase1() throws Exception {
        // Load the profile into the repository
        LoadProfile lp = new LoadProfile();
        lp.setXmlProfile(Utils.getContents(new File("files/NIST_DemoProfile_ADTA04.xml")));
        String oid1 = rStub.loadProfile(lp).get_return();

        // Load the resource into the repository
        LoadResource lr = new LoadResource();
        lr.setXmlResource(Utils.getContents(new File("files/localTables.xml")));
        String oid2 = rStub.loadResource(lr).get_return();

        // Bind the profile and the resource together
        Bind bind = new Bind();
        bind.setProfileOID(oid1);
        bind.setResourceOID(oid2);
        String oid3 = rStub.bind(bind).get_return();

        // Load NIST HL7 message context
        String xmlValidationContext = getValidationContext(new File("files/MVCCheckComponent.xml"));

        // Build the Gazelle XML Reference Standard file
        String xmlReferenceStandard = getReferenceStandard();

        // Build the Gazelle Message MetaData file
        String xmlMetaData = getMetaData("English", oid3);

        // Set the message to be validated
        String message = Utils.getContents(
                new File("files/NIST_DemoMessage_ADTA04.er7"));

        // Check the status of the service
        String xmlValidationServiceStatus =
            mvStub.getValidationServiceStatus().get_return();
        System.out.println(xmlValidationServiceStatus);

        if (!xmlValidationServiceStatus.equals("OK")) {
            throw new Exception("Service Status.");
        }

        // Set the Gazelle objectGUID
        String objectGUID1 = "12334-8942";

        validateAndDisplay(objectGUID1, xmlReferenceStandard, xmlValidationContext,
                xmlMetaData, message);
    }

    /**
     * Build the Gazelle Message MetaData file
     * @param encodedCharacter the encoded character (can be: English or ASCII)
     * @return
     */
    private static String getMetaData(String encodedCharacter, String messageProfileIdentifier) {
        MessageMetaDataDocument msgMetaDataDoc =
            MessageMetaDataDocument.Factory.newInstance();
        MessageMetaDataType msgMetaData = msgMetaDataDoc.addNewMessageMetaData();
        msgMetaData.setEncodedCharacter(encodedCharacter);
        msgMetaData.setMessageProfileID(messageProfileIdentifier);
        return msgMetaDataDoc.toString();
    }

    /**
     * Build the Gazelle XML Reference Standard file
     * @return
     */
    private static String getReferenceStandard() {
        ReferencedStandardDocument refStandardDoc =
            ReferencedStandardDocument.Factory.newInstance();
        ReferencedStandard refStandard = refStandardDoc.addNewReferencedStandard();
        // mandatory
        refStandard.setStandardName("HL7");
        refStandard.setStandardVersion("2.5");
        return refStandardDoc.toString();
    }

    /**
     * Build the Gazelle validation context
     * @param oid the oid to use: profile OID or resource OID
     * @param file the nist mvc
     * @return
     * @throws XmlException
     * @throws IOException
     */
    private static String getValidationContext(File file) throws XmlException, IOException {
        NISTHL7V2ValidationContextDefinitionDocument mvc =
            NISTHL7V2ValidationContextDefinitionDocument.Factory.parse(
                    new File("files/MVCCheckComponent.xml"));

        ValidationContextDocument validContextDoc =
            ValidationContextDocument.Factory.newInstance();
        ValidationContextType validContext = validContextDoc.addNewValidationContext();
        validContext.setGenerateSummaryResults("True");
        validContext.setGenerateDetailedResults("True");
        validContext.addNewValidationSpecificContext().
        setNISTHL7V2ValidationContextDefinition(mvc.getNISTHL7V2ValidationContextDefinition());

        return validContextDoc.toString();
    }

    /**
     * Validate and display the results
     * @param objectGUID1 ???
     * @param xmlReferenceStandard
     * @param xmlValidationContext
     * @param xmlMetaData
     * @param message
     * @throws RemoteException
     */
    private static void validateAndDisplay(String objectGUID1,
            String xmlReferenceStandard, String xmlValidationContext,
            String xmlMetaData, String message) throws RemoteException {

        // Call the Gazelle EVS Validate Method
        ValidateMessage vm = new ValidateMessage();
        vm.setObjectOID(objectGUID1);
        vm.setXmlReferencedStandard(xmlReferenceStandard);
        vm.setXmlValidationContext(xmlValidationContext);
        vm.setXmlMessageMetaData(xmlMetaData);
        vm.setXmlMessage(message);
        String xmlResultsOverview = mvStub.validateMessage(vm).get_return();

        // Display xmlResultsOverview
        System.out.println(xmlResultsOverview);

        // Summary Results
        String xmlSummaryResults = mvStub.getSummaryResults(new GetSummaryResults()).get_return();
        System.out.println(xmlSummaryResults);

        // Detailed Results
        String xmlDetailedResults = mvStub.getDetailedResults(new GetDetailedResults()).get_return();
        System.out.println(xmlDetailedResults);
    }
}
