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

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

      #region PrivateFunctions
      /// <summary>
      /// Finalizer
      /// </summary>
      ~FlowMeterDataLogWorker()
      {
         // 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)
      {
         if (disposing)
         {
            _fileWriter.Dispose();

            _quitEvent.Dispose();
         }
      }
      #endregion

      #region PublicFunctions
      /// <summary>
      /// 
      /// </summary>
      /// <param name="controller"></param>
      /// <param name="logFileName"></param>
      /// <param name="threadRestTimeMs"></param>
      /// <param name="callback"></param>
      public FlowMeterDataLogWorker(ChillerCartMeasurementManager controller, string logFileName, int threadRestTimeMs, ChillerCartMeasurementManager.FlowMeterDelegate callback)
      {
         _logger = LogManager.GetCurrentClassLogger();

         _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, Flow");
         }
      }

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

         GC.SuppressFinalize(this);
      }

      /// <summary>
      /// 
      /// </summary>
      public void DoWork()
      {
         try
         {
            while (_threadQuitControl == false)
            {
               try
               {
                  if (_quitEvent.WaitOne(_threadRestTimeMs))
                  {
                     _threadQuitControl = true;
                  }
                  else
                  {
                     double flow = _controller.FlowMeterReadFlow();

                     string logData = Util.GetTimeString() + "," + flow.ToString();

                     _fileWriter.WriteLine(logData);

                     //Invoke the callback if valid
                     if (_callback != null && _threadQuitControl == false)
                     {
                        _callback.Invoke(flow, 0);
                     }
                  }
               }
               catch (Exception e)
               {
                  string msg = e.Message;

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

                  //Invoke the callback if valid
                  if (_callback != null && _threadQuitControl == false)
                  {
                     _callback.Invoke(-1, -1);
                  }
               }
            }
         }
         catch (Exception)
         {
            //Send error code to callback if valid
            if (_callback != null && _threadQuitControl == false)
            {
               _callback.Invoke(-1, -1);
            }
         }
      }

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

         _quitEvent.Set();
      }
      #endregion
   }
}
