using System;
using System.Collections.Generic;
using System.Text;
using iNTERFACEWARE.IGC;

namespace IGCexample
{
    class IGCexampleMain
    {
        public System.Threading.AutoResetEvent StopEvent;
        public MessageProcessor Processor;
        public bool MessageSent;

        IGCexampleMain()
        {
            Processor = new MessageProcessor();
            StopEvent = new System.Threading.AutoResetEvent(false);
            MessageSent = false;
        }

        // This event is triggered when Iguana makes a request for a message.
        // Note that the message is not considered successfully sent until Iguana generates
        // a MessageRequestCompleted event.
        public void MessageRequestHandler(object sender, System.EventArgs e,
            MessageRequestResponse MessageResponse)
        {
            // Note that exceptions can never be thrown outside the handler.
            try
            {
                // This example simply sends a single hard-coded message.
                if (MessageSent == false)
                {
                    // Load OutboundMessage with the message to be sent to Iguana.
                    MessageResponse.OutboundMessage = "MSH|^~\\&|MESA_OP|XYZ_HOSPITAL|MESA_OF|XYZ_RADIOLOGY|" +
                    "||ORM^O01|102126|P|2.3.1||||||||\rPID|||583030^^^ADT1||BROWN^JAMES||19501216|M||AI|" +
                    "537 PURDUE AVE^^ST. LOUIS^MO^63130|||||||20-95-2000||||||||||||\rPV1||I||||||||||||" +
                    "|||||V1001^^^ADT1|||||||||||||||||||||||||||||||||\rORC|CA|A102Y^MESA_ORDPLC|||||||" +
                    "||||||||||";
                    MessageResponse.MessageId = System.DateTime.Now.ToString();
                    System.Console.WriteLine("*** Message sent on " + MessageResponse.MessageId + " ***");
                    System.Console.WriteLine(MessageResponse.OutboundMessage);
                }
                else
                {
                    // If the message has been successfully sent, assign the empty string to OutboundMessage.
                    // This tells Iguana that there are no new messages to be sent. Iguana will keep
                    // polling this channel - and receiving this empty string - until the channel is stopped.
                    MessageResponse.OutboundMessage = "";
                }

                // If the plugin detects an error when trying to create a message, set OutboundMessage
                // to contain a description of the error, and set MessageIsError to true.
                //
                //    MessageResponse.OutboundMessage = "Error detected when trying to send message";
                //    MessageResponse.MessageIsError = true;

                // You can use StopChannel, StopChannelErrorFlag, and StopChannelReason to stop the Iguana 
                // channel with or without an error flag, and provide a reason for the stop request.
                //
                //    MessageResponse.StopChannel = true;
                //    MessageResponse.StopChannelErrorFlag = true;
                //    MessageResponse.StopChannelReason = "An error occurred.";

                // You can send additional error/info/debug log messages to Iguana with addLogMessage().
                //
                //    MessageResponse.addLogMessage( IGClogMessageType.Error, "Error log message" );
                //    MessageResponse.addLogMessage( IGClogMessageType.Info,  "Info log message" );
                //    MessageResponse.addLogMessage( IGClogMessageType.Debug, "Debug log message" );
                //    MessageResponse.addLogMessage( IGClogMessageType.Warning, "Warning log message" );

                // You can use addLogValue() to send additional Key/Value pair logging information to Iguana.
                //
                //    MessageResponse.AddLogValue("MyField", "Message successfully processed.");
            }
            catch (iNTERFACEWARE.IGC.Exception Error)
            {
                System.Console.WriteLine(Error.Description);
            }
            catch (System.Exception Error)
            {
                System.Console.WriteLine(Error.Message);
            }
        }

        // This event is triggered when Iguana has completed processing a message that was sent by
        // OnMessageRequest.
        // If this event is not received, the message sent by the MessageRequest event handler was
        // not processed successfully. This means that the message may need to be resent.
        public void MessageRequestCompletedHandler(object sender, System.EventArgs e, string MessageID,
            bool Succeeded)
        {
            // Note that exceptions can never be thrown outside the handler.
            try
            {
                System.Console.WriteLine("*** Message sent successfully ***");
                MessageSent = true;
            }
            catch (iNTERFACEWARE.IGC.Exception Error)
            {
                System.Console.WriteLine(Error.Description);
            }
            catch (System.Exception Error)
            {
                System.Console.WriteLine(Error.Message);
            }
        }

        // This event is triggered when the connection to Iguana is closed.
		public void DisconnectHandler( object sender, System.EventArgs e, 
			MessageProcessor.IGCdisconnectReasonFlags ReasonFlags, string ReasonDescription )
		{
            // Note that exceptions can never be thrown outside the handler.
            try
			{
                // Stop the main thread and exit the program.
                if ( MessageProcessor.isDisconnectByError( ReasonFlags ) )
				{
					System.Console.WriteLine( "Connection closed by error: " + ReasonDescription );
				}
				else if ( MessageProcessor.isDisconnectByPlugin( ReasonFlags  ) )
				{
					System.Console.WriteLine( "Plugin closed the connection" );
				}
				else if ( MessageProcessor.isDisconnectByIguana( ReasonFlags ) )
				{
					System.Console.WriteLine( "Iguana closed the connection" );
				}
				else
				{
					System.Console.WriteLine( "Connection closed: " + ReasonDescription );
				}

				StopEvent.Set();
			}
			catch(iNTERFACEWARE.IGC.Exception Error)
			{
				System.Console.WriteLine(Error.Description);
			}		
			catch(System.Exception Error)
			{
				System.Console.WriteLine(Error.Message);
			}
		}

        static void Main(string[] args)
        {
            // Usage matches default executable parameters passed in by Iguana: $hostname$ $port$ $channel$ $component$
            const string Usage = "Usage: IGCexample.exe Hostname Port Channel Component";

            try
            {
                if (args.Length != 4)
                {
                    throw new System.Exception("Invalid number of command-line arguments.");
                }

                string Hostname = args[0];
                int Port = System.UInt16.Parse(args[1]);
                string Channel = args[2];
                string Component = args[3];
                
                if ( Component != "source" )
                {
                    throw new System.Exception("Invalid component - only 'source' is supported by this plugin.");
                }

                // Construct the message processor.
                IGCexampleMain Main = new IGCexampleMain();

                // Attach the event handlers to the processor.
                Main.Processor.OnDisconnect +=
                    new MessageProcessor.IGCmessageProcessorOnDisconnect(Main.DisconnectHandler);
                Main.Processor.OnMessageRequest +=
                    new MessageProcessor.IGCmessageProcessorOnMessageRequest(Main.MessageRequestHandler);
                Main.Processor.OnMessageRequestCompleted +=
                    new MessageProcessor.IGCmessageProcessorOnMessageRequestCompleted(
                    Main.MessageRequestCompletedHandler);

                // Connect to Iguana. 
                System.Console.WriteLine("Connecting to Iguana");
                Main.Processor.connect(Hostname, Port, Channel, Component);

                // Wait for the stop event, which is generated when the Iguana channel is stopped
                Main.StopEvent.WaitOne();

                return;
            }
            catch (iNTERFACEWARE.IGC.Exception Error)
            {
                System.Console.WriteLine(Error.Description);
            }
            catch (System.Exception Error)
            {
                System.Console.WriteLine(Error.Message);
            }

            System.Console.WriteLine(Usage);
        }
    }
}
