using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;

namespace OrdersRestSampleCodeCS
{
    /// <summary>
    /// Class OrderRestSample submits lab order (HL7 messages) to the MedPlus
    /// Hub platform via REST web service.
    /// </summary>
    class OrderRestSample
    {
        // USERNAME designates the Hub user name used to
        // authenticate to the Hub web service
        private const string USERNAME = "test";

        // PASSWORD designates the password associated with
        // the Hub user when authenticating to the web service
        private const string PASSWORD = "customer1";   // default password

        // SENDING_APPLICATION designates the application that 
        // is sending the order message to Hub
        private const string SENDING_APPLICATION = "HUBWS";

        // SENDING_FACILITY designates the account number provided to you 
        // by Quest for the businessunit you are ordering tests with
        private const string SENDING_FACILITY = "97502840";

        // RECEIVING_FACILITY designates the business unit 
        // within Quest from which the labs are being ordered
        private const string RECEIVING_FACILITY = "NEL";

        /// <summary>
        /// The HL7 Order message template
        /// The following "template" is used in constucting the Order.
        /// Replacement fields are:
        /// 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
        /// </summary>
        private string ORDER_MESSAGE = "MSH|^~\\&|{0}|{1}||{2}|{3:yyyyMMddHHmm}||ORM^O01|{4}|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}||||||||||OTH030^MICHIGAN^JOHN^^^^^UPIN|\r" +
                                       "OBR|1|{4}||^^^6399^CBC|||20051223094800|||||||||OTH030^MICHIGAN^JOHN^^^^^UPIN|||||||||||1^^^^^R|\r" +
                                       "DG1|1|ICD|0039|SALMONELLA INFECTION NOS|\r";

        private const char CR = (char)13;
        private const char LF = (char)10;
        private string NEWLINE = string.Format("{0}{1}", CR, LF);
        private string HL7_LINEBREAK = string.Format("{0}", CR);

        /// <summary>
        /// Submit hub order via REST web service interface. Supply REST web service
        /// endpoint url as string argument.
        /// </summary>
        public void submitOrderViaRest(string targetUrl)
        {
            HttpWebResponse response = null;
            Stream postStream = null;

            //------------------------------------------------------------------------
            //STEP 1: CONFIGURE CONNECTION TO REST ENDPOINT WITH BASIC AUTHENTICATION
            //------------------------------------------------------------------------
            HttpWebRequest request = getWebRequest(new Uri(targetUrl));
            request.Method = "POST";
            request.ContentType = "text/plain";
            request.Credentials = new NetworkCredential(USERNAME, PASSWORD);

            //----------------------------------------------------
            //STEP 2: FORMAT THE ORDER SUBMISSION REQUEST MESSAGE
            //----------------------------------------------------
            string orderMessage = buildOrderMessage(SENDING_APPLICATION, SENDING_FACILITY, RECEIVING_FACILITY);
            string encodedText = Convert.ToBase64String(UTF8Encoding.UTF8.GetBytes(orderMessage));

            //----------------------------------------------------
            //STEP 3: SUBMIT THE REQUEST TO THE HUB REST SERVICE
            //----------------------------------------------------
            try
            {
                postStream = request.GetRequestStream();
                postStream.Write(UTF8Encoding.UTF8.GetBytes(encodedText), 0, encodedText.Length);
            }
            finally
            {
                if (postStream != null) postStream.Close();
            }

            //---------------------------------------------------------------
            //STEP 4: READ RESPONSE FROM THE HUB, DECODE AND ECHO TO CONSOLE
            //---------------------------------------------------------------
            try
            {
                response = (HttpWebResponse)request.GetResponse();
                StreamReader reader = new StreamReader(response.GetResponseStream());
                byte[] decodedBytes = Convert.FromBase64String(reader.ReadToEnd());

                string lines = UTF8Encoding.UTF8.GetString(decodedBytes).Replace(HL7_LINEBREAK, NEWLINE);
                Console.Write(lines);
            }
            finally
            {
                if (response != null) response.Close();
            }
        }

        /// <summary>
        /// Returns an HttpWebRequest object to use to communicate with the REST web
        /// service. Broken out here just because it can throw an exception which has
        /// the potential to halt the run.
        /// </summary>
        private HttpWebRequest getWebRequest(Uri target)
        {
            HttpWebRequest result = null;
            try
            {
                result = (HttpWebRequest)WebRequest.Create(target);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Environment.Exit(0);
            }
            return result;
        }

        /// <summary>
        /// the buildOrderMessage function replaces values in the ORDER_MESSAGE template to
        /// create a valid HL7 Order message
        /// </summary>
        /// <param name="sendingApplication"></param>
        /// <param name="sendingFacility"></param>
        /// <param name="receivingFacility"></param>
        /// <returns></returns>
        private string buildOrderMessage(
            string sendingApplication,
            string sendingFacility,
            string receivingFacility)
        {
            //'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
            System.DateTime now = System.DateTime.Now;
            // parameters for replacement in the template
            Object[] msgParams = new Object[7];
            msgParams[0] = sendingApplication;
            msgParams[1] = sendingFacility;
            msgParams[2] = receivingFacility;
            msgParams[3] = now;
            msgParams[4] = now.Ticks;
            return string.Format(ORDER_MESSAGE, msgParams);
        }
    }
}
