'---------------------------------------------------------------------------------
' Microsoft (R) .NET Services
' Software Development Kit
' 
' Copyright (c) Microsoft Corporation. All rights reserved.  
'
' THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
' EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES 
' OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 
'---------------------------------------------------------------------------------

Imports System
Imports System.Text
Imports System.Linq
Imports System.Net
Imports System.Collections.Specialized
Namespace Microsoft.Samples.ServiceBus

    Friend Class Program
        Shared Sub Main(ByVal args() As String)
            Console.Write("Please enter your Service Namespace: ")
            Dim serviceNamespace As String = Console.ReadLine()
            Console.Write("Please enter the key for the 'owner' issuer: ")
            Dim ownerKey As String = Console.ReadLine()
            Dim bufferName As String = Guid.NewGuid().ToString("N")
            Dim messageBufferLocation As String = String.Format("http://{0}.servicebus.windows.net/{1}", serviceNamespace, bufferName)

            ' Get the ACS token
            Dim token As String = Program.GetToken(messageBufferLocation, serviceNamespace, ownerKey)

            ' Create the auth header from the token 
            Dim authHeaderValue As String = String.Format("WRAP access_token=""{0}""", token)

            ' Create the message buffer
            Dim webClient As WebClient = Program.CreateMessageBuffer(serviceNamespace, bufferName, authHeaderValue)
            Console.WriteLine("Message buffer was created at '{0}'.", messageBufferLocation)

            ' Send two message
            Program.SendMessage(webClient, authHeaderValue, "text/xml", "<msg1>This is message #1</msg1>")
            Program.SendMessage(webClient, authHeaderValue, "text/xml", "<msg2>This is message #2</msg2>")

            ' Retrieve the first message
            Dim payload As String = Program.RetrieveMessage(webClient, authHeaderValue)
            Console.WriteLine("Retrieved the message '{0}'.", payload)

            ' PeekLock the second message
            Dim lockId As String = String.Empty
            Dim messageLocation As String = String.Empty
            Dim lockLocation As String = String.Empty
            payload = Program.PeekLockMessage(webClient, authHeaderValue, messageLocation, lockId, lockLocation)
            Console.WriteLine("Locked the message '{0}'.", payload)

            Program.UnlockMessage(authHeaderValue, lockLocation)
            Console.WriteLine("Unlocked the message '{0}'.", lockLocation)

            payload = Program.PeekLockMessage(webClient, authHeaderValue, messageLocation, lockId, lockLocation)
            Console.WriteLine("Locked the message '{0}' again.", payload)

            Program.DeleteLockedMessage(authHeaderValue, messageLocation, lockId)
            Console.WriteLine("Deleted the message at '{0}'", messageLocation)

            ' Delete the message buffer
            Program.DeleteMessageBuffer(webClient, authHeaderValue)
            Console.WriteLine("Message buffer at '{0}' was deleted.", messageBufferLocation)
        End Sub

        Private Shared Function GetToken(ByVal messageBufferLocation As String, ByVal serviceNamespace As String, ByVal ownerKey As String) As String
            Dim client As New WebClient()
            client.BaseAddress = String.Format("https://{0}-sb.accesscontrol.windows.net/", serviceNamespace)
            Dim values As New NameValueCollection()
            values.Add("wrap_name", "owner")
            values.Add("wrap_password", ownerKey)
            values.Add("wrap_scope", messageBufferLocation)
            Dim responseBytes() As Byte = client.UploadValues("WRAPv0.9", "POST", values)
            Dim response As String = Encoding.UTF8.GetString(responseBytes)

            Return Uri.UnescapeDataString(response.Split("&"c).Single(Function(value) value.StartsWith("wrap_access_token=", StringComparison.OrdinalIgnoreCase)).Split("="c)(1))
        End Function

        Private Shared Function CreateMessageBuffer(ByVal serviceNamespace As String, ByVal bufferName As String, ByVal authHeaderValue As String) As WebClient
            Dim policy As String = "<entry xmlns=""http://www.w3.org/2005/Atom"">" & "<content type=""text/xml"">" & "<MessageBufferPolicy xmlns=""http://schemas.microsoft.com/netservices/2009/05/servicebus/connect""/>" & "</content>" & "</entry>"

            Dim webClient As New WebClient()
            webClient.BaseAddress = String.Format("https://{0}.servicebus.windows.net/{1}/", serviceNamespace, bufferName)
            webClient.Headers(HttpRequestHeader.ContentType) = "application/atom+xml;type=entry;charset=utf-8"
            webClient.Headers(HttpRequestHeader.Authorization) = authHeaderValue
            webClient.UploadData(String.Empty, "PUT", Encoding.UTF8.GetBytes(policy))

            Return webClient
        End Function

        Private Shared Sub SendMessage(ByVal webClient As WebClient, ByVal authHeaderValue As String, ByVal contentType As String, ByVal payload As String)
            webClient.Headers(HttpRequestHeader.ContentType) = contentType
            webClient.Headers(HttpRequestHeader.Authorization) = authHeaderValue
            webClient.UploadData("messages?timeout=20", "POST", Encoding.UTF8.GetBytes(payload))
        End Sub

        Private Shared Function RetrieveMessage(ByVal webClient As WebClient, ByVal authHeaderValue As String) As String
            webClient.Headers(HttpRequestHeader.Authorization) = authHeaderValue
            Return Encoding.UTF8.GetString(webClient.UploadData("messages/head?timeout=20", "DELETE", New Byte() {}))
        End Function

        Private Shared Function PeekLockMessage(ByVal webClient As WebClient, ByVal authHeaderValue As String, <System.Runtime.InteropServices.Out()> ByRef messageLocation As String, <System.Runtime.InteropServices.Out()> ByRef lockId As String, <System.Runtime.InteropServices.Out()> ByRef lockLocation As String) As String
            webClient.Headers(HttpRequestHeader.Authorization) = authHeaderValue
            Dim response() As Byte = webClient.UploadData("messages/head?timeout=20&lockduration=120", "POST", New Byte() {})
            messageLocation = webClient.ResponseHeaders("X-MS-MESSAGE-LOCATION")
            lockId = webClient.ResponseHeaders("X-MS-LOCK-ID")
            lockLocation = webClient.ResponseHeaders("X-MS-LOCK-LOCATION")

            Return Encoding.UTF8.GetString(response)
        End Function

        Private Shared Sub UnlockMessage(ByVal authHeaderValue As String, ByVal lockLocation As String)
            Dim webClient As New WebClient()
            webClient.BaseAddress = lockLocation
            webClient.Headers(HttpRequestHeader.ContentType) = "application/atom+xml;type=entry;charset=utf-8"
            webClient.Headers(HttpRequestHeader.Authorization) = authHeaderValue
            webClient.UploadData(String.Empty, "DELETE", New Byte() {})
        End Sub

        Private Shared Sub DeleteLockedMessage(ByVal authHeaderValue As String, ByVal messageLocation As String, ByVal lockId As String)
            Dim webClient As New WebClient()
            webClient.BaseAddress = String.Format("{0}?lockid={1}", messageLocation, lockId)
            webClient.Headers(HttpRequestHeader.ContentType) = "application/atom+xml;type=entry;charset=utf-8"
            webClient.Headers(HttpRequestHeader.Authorization) = authHeaderValue
            webClient.UploadData(String.Empty, "DELETE", New Byte() {})
        End Sub

        Private Shared Sub DeleteMessageBuffer(ByVal webClient As WebClient, ByVal authHeaderValue As String)
            webClient.Headers(HttpRequestHeader.Authorization) = authHeaderValue
            webClient.UploadData(String.Empty, "DELETE", New Byte() {})
        End Sub
    End Class
End Namespace