using System;
using System.IO;
using System.Net;
using System.Web.Services.Protocols;
using PrintableResultsSampleCodeCS.PrintableResultsWebService;
using Microsoft.VisualBasic;

namespace PrintableResultsSampleCodeCS
{
	/// <summary>
	/// Class PrintableResultsSample requests lab order (PDF file) from the MedPlus
	/// Hub platform.
	///
	/// Upon its construction, this class will exercise the functions relating to the
	/// Printable Results Service, which includes:
	/// 
	/// 1. Performing a new results search (batch size 5),
	///    for all provider accounts the hub user has access to,
	///    acknowledging the results, and getting more results.
	///
	/// 2. Getting an array of provider accounts for the hub user.
	///    This represents a subset of provider accounts.
	///
	/// 3. Performing a new results search (batch size 5),
	///    with a single provider account, 
	///    acknowledging the results, and getting more results.
	/// 
	/// 4. Performing a date range search (batch size 5), 
	///    acknowledging the results, and getting more results.
	/// 
	/// </summary>
	public class PrintableResultsSample
	{
		// 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 Printable Results web service
        private const string WEB_SERVICE_URL = "https://cert.hub.care360.com/resultsHub/observations/printable";

		private PrintableResultsService proxy;

		public PrintableResultsSample()
		{
			proxy = getWebServiceObject();

			// EXAMPLE 1:
			// Perform a new results search using all provider accounts.  
			// This is the most common scenario for developing vendors.
			// Return max of 5 results.
			Console.WriteLine("Performing new results search...");
			getResults(null, "", "");
			Console.WriteLine("Done with date range results search.");

			// EXAMPLE 2:
			// Perform a new results search using just one provider account.  
			// Return max of 5 results.
			String[] providerAccountsArray;
			providerAccountsArray = getProviderAccounts();
			Console.WriteLine("Performing new results search...");
			getResults(providerAccountsArray, "", "");
			Console.WriteLine("Done with date range results search.");

			// EXAMPLE 3:
			// Date range search using all provider accounts.  Max of 5 results, will 
			// acknowledge those results and then get more until they're all processed
			Console.WriteLine("Performing limited date range search...");
			getResults(providerAccountsArray, "01/01/2004", "01/01/2009");
			Console.WriteLine("Done with date range results search.");
		}


		private PrintableResultsService getWebServiceObject() 
		{
			PrintableResultsService webService;

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

			if (!(webService == null)) 
			{
				//------------------------------------------------------------------
				//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;
				}
			}

			return webService;
		}



		// The buildResultsRequest function will take the parameters for a results request and gernerate the object
		// to pass to the web method
		private ResultsRequest buildResultsRequest(String[] myProviderAccounts, string startDate, string endDate)
		{
			ResultsRequest uReq = new ResultsRequest();
			string[] asProvAccts = null;

			try
			{
				//------------------------------------------------------------------
				//STEP 1: SET PROVIDER ACCOUNTS
				//------------------------------------------------------------------
				if (myProviderAccounts != null)
				{
					uReq.providerAccountIds = asProvAccts;
				}

				//------------------------------------------------------------------
				//STEP 2: SET MAXIMUM NUMBER OF MESSAGES TO RETRIEVE AT ONCE
				//------------------------------------------------------------------
				uReq.maxMessages = 1;

				//------------------------------------------------------------------
				//STEP 3: SET DATE RANGE TO GET RESULTS
				//------------------------------------------------------------------
				if (endDate.Length > 0)
				{
					uReq.endDate = endDate;
				}

				if (startDate.Length > 0 )
				{
					uReq.startDate = startDate;
				}

				return uReq;
			}
			catch (Exception ex)
			{
				throw ex;
			}

		}

		private void getResults(String[] myProviderAccounts, String startDate, String endDate) 
		{
			bool bInitialRequest = true;
			bool bContinue = true;
			string requestID = "";
			int numPDFs = 0;
			PrintableResultsResponse myPrintableResponse = null;
			ResultsRequest printableResultsRequest;

			while (bContinue)
			{
				if (bInitialRequest)
				{
					bInitialRequest = false;
					Console.WriteLine("Making a first pass...");

					//------------------------------------------------------------------
					//STEP 1: GENERATE RESULTS REQUEST OBJECT
					//------------------------------------------------------------------
					printableResultsRequest = buildResultsRequest(myProviderAccounts, startDate, endDate);

					//--------------------------------------------------------------
					//STEP 2: SUBMIT REQUEST TO THE HUB
					//--------------------------------------------------------------
					myPrintableResponse = proxy.getResults(printableResultsRequest);

					if (myPrintableResponse == null) 
					{
						Console.WriteLine("Failed to properly call getPrintableResults WebService method.");
					}
				}
				else
				{
					Console.WriteLine("Making another pass...");
					myPrintableResponse = proxy.getMoreResults(requestID);
				}

				requestID = myPrintableResponse.requestId;
				Console.WriteLine("Request ID: " + requestID);

				if (myPrintableResponse.resultInfo == null)
				{
					Console.WriteLine("PDF not found.");
					bContinue = false;
				}
				else
				{
	                numPDFs++;
					Console.WriteLine("PDF found: " + myPrintableResponse.fileName);

					writeResultDataToFile(myPrintableResponse);

					// Acknowledge result
					Console.WriteLine("Acknowledging PDF file...");
					proxy.acknowledgeResults(requestID, myPrintableResponse.resultInfo, "");

					bContinue = (bool)myPrintableResponse.isMore;
				}			
			}
		}

		// The getProviderAccounts method will call the Hub and get a list
		// of provider accounts the hub user has access to.  It then places
		// the first one in a String array and returns the array, which can 
		// be passed to the getResults method to get results for a subset 
		// of the provider accounts the hub user has access to.
		private String[] getProviderAccounts() 
		{
			String[] asProvAccts = null;

			try 
			{
				Console.WriteLine("Getting Provider Accounts...");
				ProviderAccount[] myProviderAccounts = proxy.getProviderAccounts();

				if (myProviderAccounts != null)
				{
					if (myProviderAccounts.Length > 0) 
					{
						foreach (ProviderAccount myAccount in myProviderAccounts)
						{
							Console.WriteLine("ID: " + myAccount.accountId + ", Name: " + myAccount.accountName + ", Provider: " + myAccount.provider.name);
						}

						asProvAccts = new String[1];
						asProvAccts[0] = myProviderAccounts[0].accountId.Trim();
					}
				}

				return asProvAccts;
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.Message);
				return null;
			}

		}

		// Example of how to write the PDF out to a file
		private void writeResultDataToFile(PrintableResultsResponse myPrintableResponse) 
		{
			try 
			{
				// Open a file with the file name provided in the response object.  
				FileStream fs = new FileStream(myPrintableResponse.fileName, FileMode.OpenOrCreate);
				BinaryWriter bw = new BinaryWriter(fs);		//  Use a BinaryWriter to copy the Byte array to a file

				bw.Write(myPrintableResponse.resultData);
				bw.Close();
				fs.Close();
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.Message);
			}
		}

	}
}
