Imports System.Web
Imports System.Net
Imports System.IO
Imports System.Text

' Class OrderRestSample submits lab order (HL7 messages) to the MedPlus
' Hub platform.
'
' This class can exercise functions relating to the Orders Service, 
' which include:
'
' 1. Submitting an order.

Public Class OrdersAbnReqRestSample
    ' SUBMISSION_ENDPOINT is the web address of the Hub REST web service
    Private Const SUBMISSION_ENDPOINT As String = "https://cert.hub.care360.com/rest/orders/v1/document"
    Private Const ABN As Boolean = True
    Private Const REQ As Boolean = True
    Private Const AOE As Boolean = True

    ' USERNAME designates the Hub user name used to
    ' authenticate to the Hub web service
    Private Const USERNAME As String = "test"

    ' PASSWORD designates the password associated with
    ' the Hub user when authenticating to the web service
    Private Const PASSWORD As String = "customer1"

    ' SENDING_APPLICATION designates the application that 
    ' is sending the order message to Hub
    Private Const SENDING_APPLICATION As String = "HUBWS"

    ' SENDING_FACILITY designates the account number provided to you 
    ' by Quest for the businessunit you are ordering tests with
    Private Const SENDING_FACILITY As String = "97502840"

    ' RECEIVING_FACILITY designates the business unit 
    ' within Quest from which the labs are being ordered
    Private Const RECEIVING_FACILITY As String = "HOU"

    ' HL7 uses carriage return only = ASCII 13
    Private Const CR As Char = Chr(13)
    Private Const LF As Char = Chr(10)

    ' The HL7 Order message template - The following "template" is used in
    ' constucting 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 Shared ORDER_MESSAGE As String = "MSH|^~\&|{0}|{1}||{2}|{3:yyyyMMddHHmm}||ORM^O01|{4}|P|2.3" + Chr(13) + _
                                             "PID|1|11111|||TEST^WIFE||19451212|M|||||3102222222||||||123456789|" + Chr(13) + _
                                             "IN1|1||AUHSC|AETNA|123 ANYSTREET^2^CHICAGO^IL^60305|||A12345||||||||TEST^HUSBAND^|2||123 ANYSTREET^^CHICAGO^IL^60305|||||||||||||||||P123456R|||||||||||T|" + Chr(13) + _
                                             "GT1|1||TEST^HUSBAND^||123 ANYSTREET^^CHICAGO^IL^60305|3102222222||19451212|M|" + Chr(13) + _
                                             "ORC|NW|{4}||||||||||OTH030^MICHIGAN^JOHN^^^^^UPIN|" + Chr(13) + _
                                             "OBR|1|{4}||^^^6399^CBC|||20051223094800|||||||||OTH030^MICHIGAN^JOHN^^^^^UPIN|||||||||||1^^^^^R|" + Chr(13) + _
                                             "DG1|1|ICD|0039|SALMONELLA INFECTION NOS|" + Chr(13) + _
                                             "OBX|1||^^^A123^SOME OBSERVATION||||||||P" + Chr(13) + _
                                             "ORC|NW|{4}||||||||||OTH030^MICHIGAN^JOHN^^^^^UPIN|" + Chr(13) + _
                                             "OBR|1|{4}||^^^10809^TISSUE|||20051223094800|||||||||OTH030^MICHIGAN^JOHN^^^^^UPIN|||||||||||1^^^^^R|" + Chr(13)


    Public Sub run()
        Try
            Console.WriteLine("Calling submitAbnReqOrderViaRest...")
            Dim REST_WEB_SERVICE_URI As Uri = New Uri(SUBMISSION_ENDPOINT)
            submitOrderViaRest(REST_WEB_SERVICE_URI)
        Catch ex As Exception
            Console.WriteLine(ex.Message)
        End Try
    End Sub


    Private Function buildJSON(ByVal hl7 As String, ByVal abnSelected As Boolean, ByVal reqSelected As Boolean, ByVal aoeSelected As Boolean) As Byte()
        REM Build json string to wrap the request
        Dim json As String
        Dim first As Boolean = True


        json = "{""orderHl7"":"""
        hl7.Replace(vbCrLf, vbCr).Replace(vbLf, vbCr)
        json = json + System.Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(hl7))
        json = json + """"
        json = json + ","
        json += """documentTypes"":["

        If (abnSelected) Then
            first = False
            json += """" + "ABN" + """"
        End If
        If (reqSelected) Then
            If (Not first) Then
                json += ","
            End If
            json += """" + "REQ" + """"
            first = False
        End If
        If (aoeSelected) Then
            If (Not first) Then
                json += ","
            End If
            json += """" + "AOE" + """"
            first = False
        End If

        json += "]}"


        Return UTF8Encoding.UTF8.GetBytes(json)

    End Function

    Public Sub submitOrderViaRest(ByVal target As Uri)

        Dim response As HttpWebResponse = Nothing
        Dim postStream As Stream = Nothing

        '------------------------------------------------------------------------
        'STEP 1: CONFIGURE CONNECTION TO REST ENDPOINT WITH BASIC AUTHENTICATION
        '------------------------------------------------------------------------
        Dim request As HttpWebRequest = DirectCast(WebRequest.Create(target), HttpWebRequest)
        request.Method = "POST"
        request.ContentType = "application/json"
        request.Credentials = New NetworkCredential(USERNAME, PASSWORD)

        '----------------------------------------------------
        'STEP 2: FORMAT THE ORDER SUBMISSION REQUEST MESSAGE
        '----------------------------------------------------

        Dim orderMessage As String = buildOrderMessage(SENDING_APPLICATION, SENDING_FACILITY, RECEIVING_FACILITY)
        Dim jsonMessage() As Byte = buildJSON(orderMessage, ABN, REQ, AOE)

        '----------------------------------------------------
        'STEP 3: SUBMIT THE REQUEST TO THE HUB REST SERVICE
        '----------------------------------------------------
        Try
            postStream = request.GetRequestStream()
            postStream.Write(jsonMessage, 0, jsonMessage.Length)
        Catch e As Exception
            Console.WriteLine("ERROR " + e.Message)
        Finally
            If postStream IsNot Nothing Then postStream.Close()
        End Try

        '---------------------------------------------------------------
        'STEP 4: READ RESPONSE FROM THE HUB, DECODE AND ECHO TO CONSOLE
        '---------------------------------------------------------------
        Try
            response = DirectCast(request.GetResponse(), HttpWebResponse)
            Dim lines As String = getReplyText(response)
            Console.Write(lines)
        Catch e As Exception
            Console.WriteLine("ERROR " + e.Message)
        Finally
            If response IsNot Nothing Then response.Close()
        End Try
    End Sub

    'the buildOrderMessage function replaces values in the ORDER_MESSAGE template to create
    'a valid HL7 Order message
    Private Function buildOrderMessage(ByVal sendingApplication As String, _
                                       ByVal sendingFacility As String, _
                                       ByVal receivingFacility As String) As String
        ' 'now' is used for 2 purposes here
        ' 1 to specify the time that the message was created
        ' 2 to create a unique message control ID and order number
        Dim now As System.DateTime = System.DateTime.Now
        ' parameters for replacement in the template
        Dim msgParams(5) As Object

        msgParams(0) = sendingApplication
        msgParams(1) = sendingFacility
        msgParams(2) = receivingFacility
        msgParams(3) = now
        msgParams(4) = now.Ticks
        REM        Return ORDER_MESSAGE
        Return String.Format(ORDER_MESSAGE, msgParams)
    End Function


    Private Function getReplyText(ByVal response As HttpWebResponse) As String
        REM Parse json message, this code uses Newtonsoft library

        Dim result As String
        Try
            result = ""
            Dim reader As StreamReader = New StreamReader(response.GetResponseStream())
            Dim responseString As String = reader.ReadToEnd()
            Dim jsonreader As Newtonsoft.Json.JsonTextReader = New Newtonsoft.Json.JsonTextReader(New StringReader(responseString))
            Dim tokenName As String
            While (jsonreader.Read())
                If (jsonreader.TokenType.ToString.StartsWith("PropertyName")) Then
                    tokenName = jsonreader.Value.ToString
                    jsonreader.Read()
                    If (tokenName = "ackhl7") Then
                        Dim decoded As Byte() = System.Convert.FromBase64String(jsonreader.Value.ToString)
                        result = tokenName + " : " + vbCrLf + System.Text.Encoding.Default.GetString(decoded).Replace(vbCr, vbCrLf) + vbCrLf + vbCrLf
                    ElseIf (tokenName = "documentData" And Not (jsonreader.Value Is Nothing)) Then
                        Dim p1() As Byte = System.Convert.FromBase64String(jsonreader.Value.ToString)
                        Dim s1 = System.Text.Encoding.ASCII.GetString(p1)
                        Dim p2() As Byte = System.Convert.FromBase64String(s1)
                        Dim s2 = System.Text.Encoding.ASCII.GetString(p2)
                        DisplayPDF(p2)
                    ElseIf (Not (jsonreader.Value Is Nothing)) Then
                        result = result + tokenName + " : " + jsonreader.Value.ToString + vbCrLf
                    End If
                End If
            End While

        Finally
            response.Close()
        End Try
        Return result
    End Function

    Private Sub DisplayPDF(ByVal pdfBytes As Byte())
        Try
            Dim sFileName As String = "tmp.PDF"
            Dim fs As New FileStream(sFileName, FileMode.OpenOrCreate)
            Dim bw As New BinaryWriter(fs)

            bw.Write(pdfBytes)
            bw.Close()
            fs.Close()

            Process.Start("tmp.PDF")
        Catch ex As Exception
            MsgBox("Error displaying pdf:" + vbNewLine + ex.Message, MsgBoxStyle.OkOnly, "ABN/REQ Client")

        End Try
    End Sub
End Class
