//                           UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.

THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.

UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/

using System;
using System.IO.Ports;
using System.Net.Sockets;
using System.Text;
using NLog;
using Raytheon.Common;

namespace Raytheon.Instruments
{
	/// <summary>
	/// Temperature monitor class used to interact with the M3446 temperature sensor.
	/// Parsing assumes Echo mode is turned off (front panel of instrument)
	/// </summary>
	public class TempMonitorOmegaM3446 : ITempMonitor
	{
		#region PrivateMembers
		//Commands
		private const string _CARRIAGE_RTN = "\r";
		private const string _TEMP = "*X03";
		private const string _VERSION = "*U03";

		//Prevent Collisions
		private static object m_sync = new object();

		private readonly string _ipAddr;
		private readonly int _port;
		private const int _READ_BUFFER_SIZE = 128;
		private const int _READ_TIMEOUT = 5000;
		private byte[] _readBuffer;
		private NetworkStream _tcpStream;
		/// <summary>
		/// NLog logger
		/// </summary>
		private readonly ILogger _logger;
		/// <summary>
		/// Raytheon configuration
		/// </summary>
		private readonly IConfigurationManager _configurationManager;
		private readonly IConfiguration _configuration;

		public string DetailedStatus => throw new NotImplementedException();

		public bool DisplayEnabled { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
		public bool FrontPanelEnabled { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

		public InstrumentMetadata Info => throw new NotImplementedException();

		public string Name { get; set; }

		public SelfTestResult SelfTestResult => throw new NotImplementedException();

		public State Status => throw new NotImplementedException();

		#endregion

		#region PrivateFunctions
		/// <summary>
		/// Destructor
		/// </summary>
		~TempMonitorOmegaM3446()
		{
			Dispose(false);
		}

		/// <summary>
		/// Dispose of this object's resources
		/// </summary>
		/// <param name="disposing">Currently disposing</param>
		protected virtual void Dispose(bool disposing)
		{
			try
			{
				if (disposing)
				{
					//Close Connection (if available)
					_tcpStream?.Close();

				}
			}
			catch (Exception)
			{
				try
				{
					//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
				}
				catch (Exception)
				{
					//Do not rethrow. Exception from error logger that has already been garbage collected
				}
			}
		}

		/// <summary>
		/// Open socket to the temperature sensor
		/// </summary>
		private void ConnectEthernet()
		{
			//Create and open a socket to temperature sensor
			TcpClient tempSocket = new TcpClient(_ipAddr, _port);
			_tcpStream = tempSocket.GetStream();
			_tcpStream.ReadTimeout = _READ_TIMEOUT;
		}


		/// <summary>
		/// Get the current version of software loaded on temperature sensor
		/// </summary>
		private void GetSoftwareVersion()
		{
			lock (m_sync)
			{
				//Request the software version
				string rsp = SendMessageGetResponse(_VERSION);
			}
		}

		/// <summary>
		/// Send a command to the temperature sensor and request a response
		/// </summary>
		/// <param name="cmd">Command to send.</param>
		/// <returns>Response from the temperature sensor.</returns>
		private string SendMessageGetResponse(string cmd)
		{
			lock (m_sync)
			{
				//Format the command before sending
				string commandString = cmd + _CARRIAGE_RTN;

				//convert to byte array for sending
				byte[] commandBuffer = Encoding.ASCII.GetBytes(commandString);

				//send the data
				_tcpStream.Write(commandBuffer, 0, commandBuffer.Length);

				//clear the buffer
				Array.Clear(_readBuffer, 0, _readBuffer.Length);

				//read from the response buffer
				int numBytesRead = _tcpStream.Read(_readBuffer, 0, _readBuffer.Length);

				//convert response to a string
				string rspStr = Encoding.ASCII.GetString(_readBuffer);

				//Check Response
				if (rspStr.Contains(_CARRIAGE_RTN))
				{
					char[] delimit = { '\r' };
					string[] parsed = rspStr.Split(delimit, StringSplitOptions.RemoveEmptyEntries);

					//Return parsed message
					return parsed[0];
				}
				else
				{
					throw new Exception("Command message not successful");
				}
			}
		}

		#endregion

		#region PublicFunctions

		/// <summary>
		/// TempMonitorOmegaM3446 factory constructor
		/// </summary>
		/// <param name="deviceName"></param>
		/// <param name="configurationManager"></param>
		public TempMonitorOmegaM3446(string deviceName, IConfigurationManager configurationManager, ILogger logger)
		{
			Name = deviceName;

			_logger = logger;

			_configurationManager = configurationManager;
			_configuration = _configurationManager.GetConfiguration(Name);


			_ipAddr = _configuration.GetConfigurationValue("TempMonitorOmegaM3446", "IpAddr", "");
			_port = _configuration.GetConfigurationValue("TempMonitorOmegaM3446", "Port", 0);

			_readBuffer = new byte[_READ_BUFFER_SIZE];

			//Connect to device
			ConnectEthernet();
		}


		/// <summary>
		/// Constructor for the temperature sensor
		/// </summary>
		/// <param name="name">the name</param>
		/// <param name="ipAddress">IP Address of the equipment</param>
		/// <param name="port">Port of the equipment</param>
		public TempMonitorOmegaM3446(string name, string ipAddress, int port)
		{
			Name = name;
			_logger = LogManager.GetCurrentClassLogger();
			_ipAddr = ipAddress;
			_port = port;

			//Initialize read buffer
			_readBuffer = new byte[_READ_BUFFER_SIZE];

			ConnectEthernet();
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="name"></param>
		/// <param name="comPortName"></param>
		/// <param name="delayBeforeReadMs"></param>
		/// <param name="baudRate"></param>
		/// <param name="parity"></param>
		/// <param name="dataBits"></param>
		/// <param name="stopBits"></param>
		public TempMonitorOmegaM3446(string name, string comPortName, uint delayBeforeReadMs, int baudRate = 115200, Parity parity = Parity.None, int dataBits = 8, StopBits stopBits = StopBits.One)
		{
			throw new NotImplementedException();
		}


		// This code added to correctly implement the disposable pattern.
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly")]
		public void Dispose()
		{
			try
			{
				lock (m_sync)
				{
					Dispose(true);

					GC.SuppressFinalize(this);
				}
			}
			catch (Exception)
			{
				try
				{
					//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
				}
				catch (Exception)
				{
					//Do not rethrow. Exception from error logger that has already been garbage collected
				}
			}
		}

		/// <summary>
		/// Returns the current temperature read by temperature sensor
		/// </summary>
		/// <returns>The current Temperature reading</returns>
		public double ReadTemperature()
		{
			lock (m_sync)
			{
				//Request current temp reading
				string rsp = SendMessageGetResponse(_TEMP);

				return double.Parse(rsp);
			}
		}

		public bool ClearErrors()
		{
			throw new NotImplementedException();
		}

		public void Initialize()
		{
			throw new NotImplementedException();
		}

		public SelfTestResult PerformSelfTest()
		{
			throw new NotImplementedException();
		}

		public void Reset()
		{
			throw new NotImplementedException();
		}

		public void Shutdown()
		{
			throw new NotImplementedException();
		}

		#endregion
	}
}
