//                           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.Threading;
using Raytheon.Common;
using System.IO;
using MeasurementManagerLib;

namespace ChillerCartMeasurementManagerLib
{
   /// <summary>
   /// A worker class that will periodically query the temperature sensor for its status and log it out
   /// </summary>
   internal class TempDataLogWorker : IWorkerInterface
   {
      #region PrivateMembers
      private bool _threadQuitControl;
      private bool _createHeader;
      private AutoResetEvent _quitEvent;
      private StreamWriter _fileWriter;
      private readonly ChillerCartMeasurementManager _controller;
      private readonly ChillerCartMeasurementManager.TemperatureDelegate _callback;
      private readonly string _logFileName;
      private readonly int _threadRestTimeMs;

      #endregion

      #region PrivateFunctions
      /// <summary>
      /// Finalizer
      /// </summary>
      ~TempDataLogWorker()
      {
         // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
         Dispose(false);
      }


      /// <summary>
      /// 
      /// </summary>
      /// <param name="disposing"></param>
      protected virtual void Dispose(bool disposing)
      {
         try
         {
            if (disposing)
            {
               _fileWriter.Dispose();

               _quitEvent.Dispose();
            }
         }
         catch (Exception err)
         {
            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
            }
         }
      }
      #endregion

      #region PublicFunctions

      /// <summary>
      /// 
      /// </summary>
      /// <param name="controller"></param>
      /// <param name="logFileName"></param>
      /// <param name="threadRestTimeMs"></param>
      /// <param name="callback"></param>
      public TempDataLogWorker(ChillerCartMeasurementManager controller, string logFileName, int threadRestTimeMs, ChillerCartMeasurementManager.TemperatureDelegate callback)
      {
         _threadQuitControl = false;
         _quitEvent = new AutoResetEvent(false);

         _createHeader = true;

         _controller = controller;

         _callback = callback;
         _threadRestTimeMs = threadRestTimeMs;
         _logFileName = logFileName;

         //If file exists
         if (File.Exists(_logFileName))
         {
            _createHeader = false;
         }

         //Create file or append to file
         _fileWriter = new StreamWriter(_logFileName, true);
         _fileWriter.AutoFlush = true;

         //Create the header for the new file
         if (_createHeader)
         {
            _fileWriter.WriteLine("Time, Temperature, Temperature Setpoint");
         }
      }


      /// <summary>
      /// Dispose of this object. Needed for releasing thread/comm resources
      /// </summary>
      public void Dispose()
      {
         try
         {
            Dispose(true);

            GC.SuppressFinalize(this);
         }
         catch (Exception err)
         {
            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>
      /// 
      /// </summary>
      public void DoWork()
      {
         try
         {
            while (_threadQuitControl == false)
            {
               try
               {
                  if (_quitEvent.WaitOne(_threadRestTimeMs))
                  {
                     _threadQuitControl = true;
                  }
                  else
                  {
                     double temp = _controller.TemperatureSensorReadTemperature();

                     string logData = Util.GetTimeString() + ", Flow: " + temp.ToString();

                     _fileWriter.WriteLine(logData);

                     //Invoke the callback if valid
                     if (_callback != null && _threadQuitControl == false)
                     {
                        _callback.Invoke(temp, 0);
                     }
                  }
               }
               catch (Exception e)
               {
                  string msg = e.Message;
                  ErrorLogger.Instance().Write(msg + "\r\n" + e.StackTrace, ErrorLogger.LogLevel.ERROR);

                  _fileWriter.WriteLine(Util.GetTimeString() + ", " + msg);

                  //Send error code to callback if valid
                  _callback?.Invoke(-1, -1);
               }
            }
            ErrorLogger.Instance().Write("TempDataLogWorker::DoWork() - exiting", ErrorLogger.LogLevel.INFO);
         }
         catch (Exception err)
         {
            ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);

            //Send error code to callback if valid
            _callback(-1, -1);
         }
      }

      /// <summary>
      /// Stops the thread, closes the datalogger and calls move file
      /// </summary>
      public void QuitWork()
      {
         _threadQuitControl = true;

         _quitEvent.Set();
      }
      #endregion
   }
}
