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

namespace Raytheon.Instruments
{
   /// <summary>
   /// </summary>
   public class JtagConsole : IJtag
   {
      #region PrivateMembers
      private string _name;
      private static object _syncObj = new Object();
      private SelfTestResult _selfTestResult;
      private State _state;

      private readonly ILogger _logger;

      private readonly IConfigurationManager _configurationManager;
      private readonly IConfiguration _configuration;

      #endregion

      #region PrivateFunctions

      /// <summary>
      /// Finalizer.
      /// </summary>
      ~JtagConsole()
      {
         Dispose(false);
      }

      /// <summary>
      /// 
      /// </summary>
      /// <param name="disposing"></param>
      protected virtual void Dispose(bool disposing)
      {
      }

      /// <summary>
      /// 
      /// </summary>
      /// <param name="bsxFilePath"></param>
      /// <param name="diag1File"></param>
      /// <param name="diag1CmdLine"></param>
      /// <param name="jobName"></param>
      /// <param name="diagFileName"></param>
      private void GetDiagData(string bsxFilePath, string diag1File, string diag1CmdLine, string jobName, string diagFileName)
      {
         ProcessStartInfo startinfo = new ProcessStartInfo(diag1File, diag1CmdLine);
         Process proc = Process.Start(startinfo);
         proc.WaitForExit();
         int exitCode = proc.ExitCode;

         // failed to get diag data
         if (exitCode != 0)
         {
            throw new Exception("Could not capture JTAG diag file. Job: " + jobName + ", Diag Name: " + diagFileName + ", please inspect the JTAG failure manually");
         }

         // copy over the output of diag output
         string outputFileName = bsxFilePath + Util.GetTimeString() + diagFileName;
         File.Copy(bsxFilePath + jobName + diagFileName, outputFileName);
      }

      #endregion

      #region PublicFuctions

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

         _logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");

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

         _selfTestResult = SelfTestResult.Unknown;
         _state = State.Uninitialized;
      }

      public JtagConsole(string deviceName)
      {
         _name = deviceName;
         _logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}");
         _selfTestResult = SelfTestResult.Unknown;
         _state = State.Uninitialized;
      }

      /// <summary>
      /// 
      /// </summary>
      /// <returns></returns>
      public bool ClearErrors()
      {
         throw new NotImplementedException();
      }

      /// <summary>
      /// 
      /// </summary>
      public string DetailedStatus
      {
         get
         {
            return "This is a JTAG Console called " + _name;
         }
      }

      /// <summary>
      /// 
      /// </summary>
      public bool DisplayEnabled
      {
         get
         {
            throw new NotImplementedException();
         }

         set
         {
            throw new NotImplementedException();
         }
      }

      /// <summary>
      /// Dispose of resources
      /// </summary>
      public void Dispose()
      {
         Dispose(true);

         GC.SuppressFinalize(this);
      }

      /// <summary>
      /// 
      /// </summary>
      public bool FrontPanelEnabled
      {
         get
         {
            throw new NotImplementedException();
         }

         set
         {
            throw new NotImplementedException();
         }
      }

      /// <summary>
      /// 
      /// </summary>
      public InstrumentMetadata Info
      {
         get
         {
            throw new NotImplementedException();
         }
      }

      /// <summary>
      /// 
      /// </summary>
      public void Initialize()
      {
         lock (_syncObj)
         {
            if (_state == State.Uninitialized)
            {
               _state = State.Ready;
            }
            else
            {
               throw new Exception("expected the state to be Uninitialized, state was: " + _state.ToString() + " on card " + _name);
            }
         }
      }

      /// <summary>
      /// 
      /// </summary>
      public string Name
      {
         get { return _name; }
         set { _name = value; }
      }

      /// <summary>
      /// 
      /// </summary>
      /// <returns></returns>
      public SelfTestResult PerformSelfTest()
      {
         lock (_syncObj)
         {
            _selfTestResult = SelfTestResult.Pass;
            return _selfTestResult;
         }
      }

      /// <summary>
      /// 
      /// </summary>
      public void Reset()
      {
         lock (_syncObj)
         {
         }
      }

      /// <summary>
      /// 
      /// </summary>
      public SelfTestResult SelfTestResult
      {
         get
         {
            return _selfTestResult;
         }
      }

      /// <summary>
      /// Perform a JTAG cob
      /// </summary>
      /// <param name="measurement">The jtag job information</param>
      /// <returns></returns>
      public int PerformJtagJob(JtagJobInfo measurement)
      {
         lock (_syncObj)
         {
            ProcessStartInfo startinfo = new ProcessStartInfo(measurement.bsxFilePath + measurement.bsxFile, measurement.bsxFileCommandline);
            Process proc = Process.Start(startinfo);
            proc.WaitForExit();
            int exitCode = proc.ExitCode;

            // test failed
            if (exitCode != 0)
            {
               if (measurement.shallWeUseDiag1 == true)
               {
                  GetDiagData(measurement.bsxFilePath, measurement.diag1File, measurement.diag1CmdLine, measurement.jobName, "_ttr.rtf");
               }

               if (measurement.shallWeUseDiag2 == true)
               {
                  GetDiagData(measurement.bsxFilePath, measurement.diag2File, measurement.diag2CmdLine, measurement.jobName, ".dia");
               }

               return exitCode;
            }
            else
            {
               return exitCode;
            }
         }
      }

      /// <summary>
      /// 
      /// </summary>
      public State Status
      {
         get
         {
            return _state;
         }
      }

      /// <summary>
      /// 
      /// </summary>
      public void Shutdown()
      {
         lock (_syncObj)
         {
            _state = State.Uninitialized;
         }
      }

      #endregion
   }
}