/*-------------------------------------------------------------------------
//                           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 ProgramLib;
using NLog;
using Raytheon.Common;
using Raytheon.Instruments;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ProgramGui;
using ProgramGui.Model;
using ProgramGui.View;
using ProgramGui.ViewModel;
using System.Windows;
using Raytheon;

namespace ProgramLib
{
   internal class UutPowerAction
   {
      #region PrivateClassMembers
      private static NLog.ILogger _logger;

      private static object powerSyncObj = new object();

      private bool _sttoSuccess = true;

      private string fatalErrorMsg;

      #endregion

      public UutPowerAction()
      {
         _logger = LogManager.GetCurrentClassLogger();
      }

      ~UutPowerAction()
      {
         _logger?.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() ...");
      }

      /// <summary>
      /// Power off UUT
      /// </summary>
      /// <param name="name"></param>
      /// <returns></returns>
      public void UutPowerOff()
      {
         try
         {
            lock (powerSyncObj)
            {
               _logger?.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() method...");

               if (Program.Instance()._isUutPwrOn)
               {
                  Program.Instance().GetPowerSupplyMeasurementManager()[PowerSupplyConstants.POWER_DEVICE.STE_POWER_SUPPLY_SYSTEM].OutputDisable(ProgramLib.PowerSupplyConstants.POWER_DEVICE.STE_PVM_5V);
                  // enable front panel
                  Program.Instance().GetPowerSupplyMeasurementManager()[PowerSupplyConstants.POWER_DEVICE.STE_POWER_SUPPLY_SYSTEM].FrontPanelEnabled = true;

                  ProgramLib.Program.Instance().GetGuiManager()[ProgramGuiManager.WINDOWS.MAIN].Dispatcher.Invoke((Action)delegate
                  {
                     ProgramLib.Program.Instance().GetGuiManager()[ProgramGuiManager.WINDOWS.MAIN].Hide();
                  });

                  Program.Instance()._eventManager[EventManager.Events.UUT_POWER_ON].Reset();
                  Program.Instance()._eventManager[EventManager.Events.UUT_POWER_OFF].Set();

                  Program.Instance()._isUutPwrOn = false;
               }
            }
         }
         catch (Exception)
         {
            throw;
         }
      }

      /// <summary>
      /// Power on UUT
      /// </summary>
      /// <param name="name"></param>
      /// <returns></returns>
      public void UutPowerOn()
      {
         try
         {
            lock (powerSyncObj)
            {
               _logger?.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() method...");

               if (!Program.Instance()._isUutPwrOn)
               {
                  Task.Factory.StartNew(() => PerformSttoTask());
                  ProgramLib.Program.Instance().GetGuiManager()[ProgramGuiManager.WINDOWS.IMPEDANCE_CHECK].Dispatcher.Invoke((Action)delegate
                  {
                     ProgramLib.Program.Instance().GetGuiManager()[ProgramGuiManager.WINDOWS.MAIN].Hide();

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

                  if (_sttoSuccess)
                  {
                     ProgramLib.Program.Instance().GetGuiManager()[ProgramGuiManager.WINDOWS.IMPEDANCE_CHECK].Dispatcher.Invoke((Action)delegate
                     {
                        ProgramLib.Program.Instance().GetGuiManager()[ProgramGuiManager.WINDOWS.MAIN].Show();
                     });

                     Program.Instance().GetPowerSupplyMeasurementManager()[PowerSupplyConstants.POWER_DEVICE.STE_POWER_SUPPLY_SYSTEM].OutputEnable(ProgramLib.PowerSupplyConstants.POWER_DEVICE.STE_PVM_5V);

                     // disable front panel
                     Program.Instance().GetPowerSupplyMeasurementManager()[PowerSupplyConstants.POWER_DEVICE.STE_POWER_SUPPLY_SYSTEM].FrontPanelEnabled = false;

                     Program.Instance()._eventManager[EventManager.Events.UUT_POWER_OFF].Reset();
                     Program.Instance()._eventManager[EventManager.Events.UUT_POWER_ON].Set();

                     Program.Instance()._isUutPwrOn = true;
                  }
                  else
                  {
                     throw new Exception(fatalErrorMsg);
                  }
               }
               else
               {
                  throw new Exception("UUT power is already on.");
               }
            }
         }
         catch (Exception)
         {
            throw;
         }
      }

      private async void PerformSttoTask()
      {
         ImpedanceDataModel impedanceDataModel;
         ImpedanceCheckWindow impedanceCheckWindow = (ImpedanceCheckWindow)ProgramLib.Program.Instance().GetGuiManager()[ProgramGuiManager.WINDOWS.IMPEDANCE_CHECK];

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

            bool forceFail = false;
            string measurementStatus = "PASSED";

            ImpedanceCheckWindowViewModel.Images passFailImage = ImpedanceCheckWindowViewModel.Images.PASS_CHECK;
            impedanceCheckWindow._viewModel.ClearData();
            int MAX_ITERATION = 15;
            int cableNum = 17;
            int cablePin1 = 5;
            int cablePin2 = 7;
            int measurement = 5;
            string measurementName;
            for (int i = 1; i <= MAX_ITERATION; i++)
            {
               measurementName = $"P{cableNum}_P{cablePin1++}_P{cableNum++}_P{cablePin2++}";
               impedanceDataModel = new ImpedanceDataModel();
               if (i == MAX_ITERATION / 2 && forceFail)
               {
                  passFailImage = ImpedanceCheckWindowViewModel.Images.FAIL_CHECK;
                  measurementStatus = "FAILED";
                  _sttoSuccess = false;
               }

               impedanceDataModel.PassFailImagePath = impedanceCheckWindow._viewModel._imageToResourcePathDict[passFailImage];
               impedanceDataModel.Description = $"{measurementName} Measured {measurement} Range [0,50]";

               if (Program.Instance()._testStandSeqContext != null)
               {
                  Program.Instance()._testStandSeqContext.Step.AdditionalResults.CustomResults.Insert($"\"{measurementName}\"", $"\"Measured: {measurement++} Range [0,50] - {measurementStatus}\"");
               }

               impedanceCheckWindow._viewModel.AddData(impedanceDataModel);

               if (!_sttoSuccess)
               {
                  fatalErrorMsg = impedanceDataModel.Description;
                  throw new Exception(fatalErrorMsg);
               }

               await Task.Delay(300);
            }
         }
         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...");
         }
      }
   }
}
