using System;
using System.Net;
using System.Web.Services.Protocols;
using PatientDemographicsSampleCodeCS.PatientDemographicsWebService;
using Microsoft.VisualBasic;

namespace PatientDemographicsSampleCodeCS
{
	/// <summary>
	/// Class PatientDemographicsSample submits demographic information (HL7 ADT messages) 
	/// to the MedPlus Hub platform.
	///
	/// Upon its construction, this class will exercise the functions relating to the
	/// Demographics Service, which includes:
	///
	/// 1. Sending a real time ADT message.
	/// 2. Sending a batch mode ADT message.
	/// </summary>
	public class PatientDemographicsSample
	{
		// 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";

		// WEB_SERVICE_URL designates the end point used to
		// connect to the Hub's Demographics web service
		private const string WEB_SERVICE_URL = "https://cert.hub.care360.com/demographic/service";

		// SENDING_APPLICATION designates the application that 
		// is sending the ADT 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 sending demographics for
		private const string SENDING_FACILITY = "1594";

		// RECEIVING_FACILITY designates the business unit 
		// within Quest which the demographics are for
		private const string RECEIVING_FACILITY = "2135800";

		// The HL7 ADT message template - The following "template" is used in
		// constucting the Demographic message.
		// 
		// 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 ADT message
		private string ADT_MESSAGE = "MSH|^~\\&|{0}|{1}||{2}|{3:yyyyMMddHHmmssss}||ADT^A28|{4}|P|2.3\r" +
								     "EVN|A28|199608190820\r" +
									 "PID|1|pid123|^^^LH||Wally^SHERRY^M||20000101|F|PETRY^SHERRY||4690 Parkway Dr.^address line 2^Mason^OH^45040^USA|a2|^^^^86^999^9999999^99999|513-999-9999|a5|||1-FOUND|444-66-9999\r" + 
									 "PV1|1|O\r" + 
									 "GT1|1|88|Smith^John^M^JR^DR^MD||3710 Emery Lake Ln^Street line2^Cincinnati^OH^45010|^^^^1^513^8888888^1234|^^^^1^238^4444444^5678|19960708112233|M|I|8|287889999||||ABC Inc.^Limited^M |4567 Kelly Drive^address line 2^Oxford^OH^45068|55566677777|4556|FT|Guarantor Organization\r" +
									 "IN1|1|INSID123^Insurance Plan ABC|INSCOID123|insuranceco|1800 Insurance Rd.^^Detroit^MI^45777||^^^^1^555^6667777^1234|3433|name|||||^19960707|||||||||||||||||||||||||||||||||T\r";

		public PatientDemographicsSample()
		{
			try
			{
				// calling sendRealTimeADTMessage will send the demographic request in
				// real time
				Console.WriteLine("Calling submitRealTimeADTMessage...");
				sendADTMessage(true);

				// calling sendBatchADTMessage will send the demographic request in
				// batch mode
				Console.WriteLine("Calling sendBatchADTMessage...");
				sendADTMessage(false);
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.Message);
			}
		}


		public void sendADTMessage(bool realTime)
		{
			DemographicService webService = null;

			try
			{
				//-------------------------------------------------------
				//STEP 1: CREATE WEB SERVICE REFERENCE
				//-------------------------------------------------------
				webService = new DemographicService();
			}
			catch (Exception ex)
			{
				Console.Write(ex.StackTrace);
				webService = null;
			}

			if (!(webService == null))
			{
				DemographicResponse response = null;
				DemographicRequest request = null;

				try
				{
					//------------------------------------------------------------------
					//STEP 2: CREATE CREDENTIALS OBJECT CONTAINING USERNAME AND PASSWORD
					//------------------------------------------------------------------
					webService.Credentials = new NetworkCredential(USERNAME, PASSWORD);

					// By default the client will attempt to call the web service without 
					// sending the credentials. If the server returns a 401 HTTP response, 
					// the client makes the call again with the credentials. If we set 
					// PreAuthenticate to True, the client will include the credentials on 
					// the initial call and eliminate this extra processing.
					//
					// This should probably be set in the web service object's constructor,
					// but has been included here to demonstrate.
					webService.PreAuthenticate = true;


					//------------------------------------------------------------------
					//STEP 3: SET WEB SERVICE URL
					//------------------------------------------------------------------
					if (WEB_SERVICE_URL.Length > 0)
					{
						webService.Url = WEB_SERVICE_URL;
					}

					//------------------------------------------------------------------
					//STEP 4: GENERATE DEMOGRAPHIC REQUEST OBJECT
					//------------------------------------------------------------------
					request = getWebServiceDemographicRequest();

					//--------------------------------------------------------------
					//STEP 5: SUBMIT ADT MESSAGE TO THE HUB
					//--------------------------------------------------------------
	
					if (realTime) 
					{
						response = webService.submitRealTimeADTMessage(request);
					}
					else
					{
						response = webService.submitBatchADTMessage(request);
					}
				}
				catch (SoapException soapEx)
				{
					string exceptionMessage = soapEx.Detail.InnerText.Replace("" +
						(char)10 + "", "" + (char)13 + "" +
						(char)10 + "");

					Console.Write(exceptionMessage);
				}

				if (!(response == null)) 
				{
					//------------------------------------------------
					//STEP 6: EXAMINE RESPONSE FROM THE HUB
					//------------------------------------------------
					Console.WriteLine("Status: <{0}>.", response.status);
					Console.WriteLine("Transaction Id: <{0}>.", response.hubTransactionUid);
					Console.WriteLine("Message Control Id: <{0}>.", response.messageControlUid);

					if (!(response.errors == null)) 
					{
						foreach (string valErr in response.errors)
						{
							Console.WriteLine("Validation Error: <{0}>.", valErr);
						}
					}
				}
				else
				{
					Console.WriteLine("Failed to properly call submitADTMessage WebService method.");
				}
			}
		}

		/// <summary>
		/// the getWebServiceDemographicRequest function creates a proper DemographicRequest object 
		/// that will be submitted to the Hub
		/// </summary>
		/// <param name="webService"></param>
		private DemographicRequest getWebServiceDemographicRequest()
		{
			DemographicRequest retval = new DemographicRequest();
			
			// Create ADT Message by passing in facility information
			String ADTMessage = buildADTMessage(SENDING_APPLICATION, SENDING_FACILITY, RECEIVING_FACILITY);
			
			// Convert String to a Byte array and return in an DemographicRequest object
			retval.ADTMessage = System.Text.Encoding.ASCII.GetBytes(ADTMessage);
			return retval;
		}

		/// <summary>
		/// the buildADTMessage function replaces values in the ADT_MESSAGE template to
		/// create a valid HL7 ADT message
		/// </summary>
		/// <param name="sendingApplication"></param>
		/// <param name="sendingFacility"></param>
		/// <param name="receivingFacility"></param>
		/// <returns></returns>
		private String buildADTMessage(
			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
			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(ADT_MESSAGE, msgParams);
		}

	}
}
