package hub.sample;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.MessageFormat;

import javax.xml.bind.DatatypeConverter;

public class OrderSubmissionAbnReqRestClient {

    /**
     * You will pass the username and password when you get the stub later in
     * this example. Via the stub, you'll make the method calls to the Results
     * Web Service to retrieve lab results.
     */
    private static final String DOCUMENT_ENDPOINT = "https://cert.hub.care360.com/rest/orders/v1/document";
    private static final String USERNAME = "test";
    private static final String PASSWORD = "customer1";

    // SENDING_APPLICATION designates the application that is sending the order
    // message to Hub
    private static final String SENDING_APPLICATION = "HUBWS";

    // SENDING_FACILITY designates the account number provided to you by Quest
    // for the business unit you are ordering tests with
    private static final String SENDING_FACILITY = "97502840";

    // RECEIVING_FACILITY designates the business unit within Quest from which
    // the labs are being ordered
    private static final String RECEIVING_FACILITY = "NEL";

    /*
     * The HL7 Order message template - The following "template" is used in
     * constructing the Order.
     * 
     * 0 = sending application (field 3) 1 = sending facility (field 4)
     * represents the account with Quest Diagnostics 2 = receiving facility
     * (field 6) The Quest Business Unit for above account 3 = date time (field
     * 7) 4 = message control id (field 10) Unique Number identifying this order
     * message
     */
    private static final String ORDER_MESSAGE = "MSH|^~\\&|{0}|{1}||{2}|{3,date,yyyyMMddHHmm}||ORM^O01|{4,number,#}|P|2.3\r"
            + "PID|1|11111|||TEST^WIFE||19451212|M|||||3102222222||||||123456789|\r"
            + "IN1|1||AUHSC|AETNA|123 ANYSTREET^2^CHICAGO^IL^60305|||A12345||||||||TEST^HUSBAND^|2||123 ANYSTREET^^CHICAGO^IL^60305|||||||||||||||||P123456R|||||||||||T|\r"
            + "GT1|1||TEST^HUSBAND^||123 ANYSTREET^^CHICAGO^IL^60305|3102222222||19451212|M|\r"
            + "ORC|NW|{4,number,#}||||||||||OTH030^MICHIGAN^JOHN^^^^^UPIN|\r"
            + "OBR|1|{4,number,#}||^^^6399^CBC|||20051223094800|||||||||OTH030^MICHIGAN^JOHN^^^^^UPIN|||||||||||1^^^^^R|\r"
            + "DG1|1|ICD|0039|SALMONELLA INFECTION NOS|\r"                                             
            + "OBX|1||^^^A123^SOME OBSERVATION||||||||P\r"
            + "ORC|NW|{4,number,#}||||||||||OTH030^MICHIGAN^JOHN^^^^^UPIN|\r" 
            + "OBR|1|{4,number,#}||^^^10809^TISSUE|||20051223094800|||||||||OTH030^MICHIGAN^JOHN^^^^^UPIN|||||||||||1^^^^^R|";

    public static void main(String[] args) throws Exception {
        // Submit the Order via REST
        requestOrderDocument();
    }

    private static void requestOrderDocument() throws Exception {
        HttpURLConnection conn = null;
        try {
            // -------------------------------------------------
            // STEP 1: CONFIGURE CONNECTION TO REST ENDPOINT
            // -------------------------------------------------
            conn = (HttpURLConnection) (new URL(DOCUMENT_ENDPOINT).openConnection());
            conn.setDoOutput(true);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type", "application/json");
            String credentials = USERNAME + ":" + PASSWORD;
            String encodedCredentials = DatatypeConverter.printBase64Binary(credentials.getBytes());
            conn.setRequestProperty("Authorization", "Basic " + encodedCredentials);

            // ------------------------------------------------------------------
            // STEP 2: ASSEMBLE AND ENCODE MESSAGE TO SEND
            // ------------------------------------------------------------------
            String encodedHl7 = DatatypeConverter.printBase64Binary(buildOrderMessage(SENDING_APPLICATION,
                    SENDING_FACILITY, RECEIVING_FACILITY).getBytes());
            String messageTemplate = "{\"orderHl7\":\"%s\",\"documentTypes\":[\"ABN\", \"REQ\", \"AOE\"]}";
            String message = String.format(messageTemplate, encodedHl7);

            // ------------------------------------------------------------------
            // STEP 3: WRITE MESSAGE TO THE OPEN CONNECTION
            // ------------------------------------------------------------------
            OutputStream os = conn.getOutputStream();
            os.write(message.getBytes());
            os.flush();

            // -------------------------------------------------
            // STEP 4: EXAMINE RESPONSE COMING BACK FROM THE HUB
            // -------------------------------------------------
            StringBuilder serverResponse = new StringBuilder();
            BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
            String line;
            while ((line = br.readLine()) != null) {
                serverResponse.append(line);
            }

            // -----------------------------------------------------------------
            // STEP 5: ECHO RESPONSE FROM THE HUB
            //
            // NOTE: expect JSON map with the following entries:
            //
            // ==========KEY========== ==============EXAMPLE VALUE==============
            // "ackhl7"                <base64 encoded HL7 response>
            // "orderSupportDocuments" <JSON array of document maps (see below)>
            //
            // Document map contents as follows:
            // ==========KEY========== ==============EXAMPLE VALUE==============
            // "documentData"          "<pdf data>"                              --see note below!
            // "documentType"          "ABN-REQ"
            // "requestStatus"         "0000: Processing Completed Successfully"
            // "responseMessage"       "REQ OK; ABN is not required"
            // "status"                "true"
            // "misc"                  null
            // "cdaRepresentation"     null
            //
            // NOTA BENE: <pdf data> is the result of having base64 encoded a 
            //            PDF document not once, but *TWICE*.
            // -----------------------------------------------------------------
            System.out.println("Response Message:");
            System.out.println(serverResponse.toString());
        } finally {
            conn.disconnect();
        }
    }

    /**
     * buildOrderMessage: constructs a valid HL7 Order message string
     */
    private static String buildOrderMessage(String sendingApplication, String sendingFacility, String receivingFacility) {
        // return value
        String retValue = null;
        // Build an Order Message for the hl7
        Object[] msgParams = new Object[7];
        // 0 = sending application (field 3)
        // 1 = sending facility (field 4)
        // 2 = receiving facility (field 6)
        // 3 = date time (field 7)
        // 4 = message control id (field 10)
        // reverse sending/receiving
        msgParams[0] = sendingApplication;
        msgParams[1] = sendingFacility;
        msgParams[2] = receivingFacility;
        msgParams[3] = new java.util.Date();
        msgParams[4] = new Long(System.currentTimeMillis()); // new message
                                                             // control id

        retValue = MessageFormat.format(ORDER_MESSAGE, msgParams);
        return retValue;
    }
}
