//---------------------------------------------------------------------------------
// 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. 
//---------------------------------------------------------------------------------

namespace Microsoft.Samples.ServiceBus
{
    using System;
    using System.Text;
    using System.Linq;
    using System.Net;
    using System.Collections.Specialized;
   
    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("Please enter your Service Namespace: ");
            string serviceNamespace = Console.ReadLine();
            Console.Write("Please enter the key for the 'owner' issuer: ");
            string ownerKey = Console.ReadLine();
            string bufferName = Guid.NewGuid().ToString("N");
            string messageBufferLocation = string.Format("http://{0}.servicebus.windows.net/{1}", serviceNamespace, bufferName);

            // Get the ACS token
            string token = Program.GetToken(messageBufferLocation, serviceNamespace, ownerKey);

            // Create the auth header from the token 
            string authHeaderValue = string.Format("WRAP access_token=\"{0}\"", token);

            // Create the message buffer
            WebClient 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
            string payload = Program.RetrieveMessage(webClient, authHeaderValue);
            Console.WriteLine("Retrieved the message '{0}'.", payload);
                            
            // PeekLock the second message
            string lockId;
            string messageLocation;
            string lockLocation;
            payload = Program.PeekLockMessage(webClient, authHeaderValue, out messageLocation, out lockId, out lockLocation);
            Console.WriteLine("Locked the message '{0}'.", payload);

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

            payload = Program.PeekLockMessage(webClient, authHeaderValue, out messageLocation, out lockId, out 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);
        }

        static string GetToken(string messageBufferLocation, string serviceNamespace, string ownerKey)
        {
            WebClient client = new WebClient();
            client.BaseAddress = string.Format("https://{0}-sb.accesscontrol.windows.net/", serviceNamespace);
            NameValueCollection values = new NameValueCollection();
            values.Add("wrap_name", "owner");
            values.Add("wrap_password", ownerKey);
            values.Add("wrap_scope", messageBufferLocation);
            byte[] responseBytes = client.UploadValues("WRAPv0.9", "POST", values);
            string response = Encoding.UTF8.GetString(responseBytes);

            return Uri.UnescapeDataString(response.Split('&').Single(value => value.StartsWith("wrap_access_token=", StringComparison.OrdinalIgnoreCase)).Split('=')[1]);           
        }

        static WebClient CreateMessageBuffer(string serviceNamespace, string bufferName, string authHeaderValue)
        {
            string policy =
                "<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>";

            WebClient webClient = 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;
        }

        static void SendMessage(WebClient webClient, string authHeaderValue, string contentType, string payload)
        {
            webClient.Headers[HttpRequestHeader.ContentType] = contentType;
            webClient.Headers[HttpRequestHeader.Authorization] = authHeaderValue;
            webClient.UploadData("messages?timeout=20", "POST", Encoding.UTF8.GetBytes(payload));
        }

        static string RetrieveMessage(WebClient webClient, string authHeaderValue)
        {
            webClient.Headers[HttpRequestHeader.Authorization] = authHeaderValue;
            return Encoding.UTF8.GetString(webClient.UploadData("messages/head?timeout=20", "DELETE", new byte[0]));
        }

        static string PeekLockMessage(WebClient webClient, string authHeaderValue, out string messageLocation, out string lockId, out string lockLocation)
        {
            webClient.Headers[HttpRequestHeader.Authorization] = authHeaderValue;
            byte[] response = webClient.UploadData("messages/head?timeout=20&lockduration=120", "POST", new byte[0]);
            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);
        }

        static void UnlockMessage(string authHeaderValue, string lockLocation)
        {
            WebClient webClient = 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[0]);
        }

        static void DeleteLockedMessage(string authHeaderValue, string messageLocation, string lockId)
        {
            WebClient webClient = 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[0]);
        }

        static void DeleteMessageBuffer(WebClient webClient, string authHeaderValue)
        {
            webClient.Headers[HttpRequestHeader.Authorization] = authHeaderValue;
            webClient.UploadData(String.Empty, "DELETE", new byte[0]);            
        }
    }    
}
 