/*-------------------------------------------------------------------------
//                           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 NLog;
using ProgramLib.GUI.Model;
using ProgramLib.GUI.View;
using ProgramLib.GUI.ViewModel;
using Raytheon.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using static MeasurementManagerLib.SwitchMeasurementManager;

namespace ProgramLib
{
   /// <summary>
	/// GMA/AUR TRD GMA_ATP_001 - UUT STTO
	/// </summary>
   internal class GMA_ATP_001_UUT_STTO : BasicTest
   {
      private readonly Dictionary<string, DMMResistanceMeasurementFields> _dmmResistanceMeasurements = new Dictionary<string, DMMResistanceMeasurementFields>(StringComparer.InvariantCultureIgnoreCase);
      private List<string> _relayExclusionList;
      private static NLog.ILogger _logger;

      private bool _sttoSuccess = false;
      private string fatalErrorMsg;

      public GMA_ATP_001_UUT_STTO()
      {
         _logger = LogManager.GetCurrentClassLogger();
         ParseMeasurementDef();
      }

      /// <summary>
      /// Execute Test
      /// </summary>
      protected override void ExecuteTest()
      {
         Task.Factory.StartNew(() => PerformSttoTask());
         ProgramLib.Program.Instance().GetGuiManager()[ProgramGuiManager.WINDOWS.IMPEDANCE_CHECK].Dispatcher.Invoke((Action)delegate
         {
            ProgramLib.Program.Instance().GetGuiManager()[ProgramGuiManager.WINDOWS.LIVE_DATA].Hide();

            ProgramLib.Program.Instance().GetGuiManager()[ProgramGuiManager.WINDOWS.IMPEDANCE_CHECK].ShowDialog();
         });

         Program.Instance().SttoSuccess = _sttoSuccess;

         if (!_sttoSuccess)
         {
            throw new Exception(fatalErrorMsg);
         }
      }

      /// <summary>
      /// Check Pre Conditions
      /// </summary>
      protected override void CheckPrerequisite()
      {
         // add pre req checks as needed
      }

      /// <summary>
		/// Perform Safe-to-turn-on checks
		/// </summary>
      private void PerformSttoTask()
      {
         ImpedanceDataModel impedanceDataModel;
         ImpedanceCheckWindow impedanceCheckWindow = (ImpedanceCheckWindow)ProgramLib.Program.Instance().GetGuiManager()[ProgramGuiManager.WINDOWS.IMPEDANCE_CHECK];

         try
         {
            _logger?.Debug($"{this.GetType().Name}::PerformSttoTask() running...");

            _sttoSuccess = true;
            string measurementStatus = "PASSED";

            ImpedanceCheckWindowViewModel.Images passFailImage = ImpedanceCheckWindowViewModel.Images.PASS_CHECK;
            impedanceCheckWindow.ViewModel.ClearData();

            foreach (KeyValuePair<string, DMMResistanceMeasurementFields> measurement in _dmmResistanceMeasurements)
            {
               impedanceDataModel = new ImpedanceDataModel();
               double testResult = Program.Instance().MalMeasurementLibManager.SwitchMeasurementManager.DmmReadResistance(measurement.Key);

               if (testResult < measurement.Value._lowerLimit || testResult > measurement.Value._upperLimit)
               {
                  passFailImage = ImpedanceCheckWindowViewModel.Images.FAIL_CHECK;
                  measurementStatus = "FAILED";
                  _sttoSuccess = false;
               }

               impedanceDataModel.PassFailImagePath = impedanceCheckWindow.ViewModel.ImageToResourcePathDict[passFailImage];
               impedanceDataModel.Description = $"{measurement.Value._cableAndPinId} Measured {testResult.ToString("0.00")} Range [{measurement.Value._lowerLimit},{measurement.Value._upperLimit}]";

               if (Program.Instance().TestStandSeqContext != null)
               {
                  Program.Instance().TestStandSeqContext.Step.AdditionalResults.CustomResults.Insert($"\"{measurement.Value._cableAndPinId}\"", $"\"Measured: {testResult.ToString("0.00")} Range [{measurement.Value._lowerLimit},{measurement.Value._upperLimit}] - {measurementStatus}\"");
               }

               impedanceCheckWindow.ViewModel.AddData(impedanceDataModel);

               if (!_sttoSuccess)
               {
                  fatalErrorMsg = impedanceDataModel.Description;
               }
            }
         }
         catch (Exception ex)
         {
            _logger.Error(ex.Message + "\n" + ex.StackTrace);
         }
         finally
         {
            if (!_sttoSuccess)
            {
               impedanceCheckWindow.Dispatcher.Invoke((Action)delegate
               {
                  impedanceCheckWindow.btnClose.Visibility = Visibility.Visible;
               });
            }
            else
            {
               impedanceCheckWindow.Dispatcher.Invoke((Action)delegate
               {
                  impedanceCheckWindow.Hide();
               });
            }

            _logger?.Debug($"{this.GetType().Name}::PerformSttoTask() exiting...");
         }
      }

      /// <summary>
		/// Parses the ini file for measurement definitions
		/// Populates the Dictionaries with the enum names and ini file data
		/// </summary>
		private void ParseMeasurementDef()
      {
         const string MAIN_SECTION_NAME = "GMA_ATP_001_UUT_STTO";
         const string DMM_RESISTANCE_SECTION_NAME = $"{MAIN_SECTION_NAME}.DMM_RESISTANCE_MEASUREMENTS";
         const string RELAY_EXCLUSION_SECTION_NAME = $"{MAIN_SECTION_NAME}.RELAY_EXCLUSION_LIST";

         const string EXCLUSION_LIST_KEY = "EXCLUSION_LIST";
         ConfigurationFile configurationFile = new ConfigurationFile(Program.Instance().TestMethodConfigFilePath);

         const char COMMA_DELIM = ',';

         // read in relay exclusion list
         string relayExclusions = configurationFile.ReadValue<string>(RELAY_EXCLUSION_SECTION_NAME, EXCLUSION_LIST_KEY);
         _relayExclusionList = relayExclusions.Split(COMMA_DELIM).ToList();

         for (int i = 0; i < _relayExclusionList.Count; ++i)
         {
            _relayExclusionList[i] = _relayExclusionList[i].TrimEnd(' ');
            _relayExclusionList[i] = _relayExclusionList[i].TrimStart(' ');
         }

         List<string> keys = configurationFile.ReadAllKeys(DMM_RESISTANCE_SECTION_NAME);
         foreach (string key in keys)
         {
            List<string> valueList = configurationFile.ReadList<string>(DMM_RESISTANCE_SECTION_NAME, key);
            
            int index = 0;
            string pcode = valueList[index++];
            double range = Convert.ToDouble(valueList[index++]);
            double res = Convert.ToDouble(valueList[index++]);
            int delay = Convert.ToInt32(valueList[index++]);
            double scaleFactor = Convert.ToDouble(valueList[index++]);

            List<string> relayList = valueList[index++].Split(COMMA_DELIM).ToList();
            for (int i = 0; i < relayList.Count; ++i)
            {
               relayList[i] = relayList[i].Trim();
            }

            string resistanceTypeStr = valueList[index++].Trim();
            DMMResistanceType type = (DMMResistanceType)Enum.Parse(typeof(DMMResistanceType), resistanceTypeStr, true);
            string cableAndPinId = valueList[index++];
            double lowerLimit = Convert.ToDouble(valueList[index++]);
            double upperLimit = Convert.ToDouble(valueList[index++]);

            _dmmResistanceMeasurements.Add(key.ToUpper(), new DMMResistanceMeasurementFields(pcode, range, res, delay, scaleFactor, relayList, type, cableAndPinId, lowerLimit, upperLimit));
         }

         Program.Instance().MalMeasurementLibManager.SwitchMeasurementManager.DmmResistanceMeasurements = _dmmResistanceMeasurements;
         Program.Instance().MalMeasurementLibManager.SwitchMeasurementManager.RelayExclusionList = _relayExclusionList;
      }
   }
}
