using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
using NLog;
using Raytheon.Common;

namespace Raytheon.Instruments
{
   [ExportInstrumentFactory(ModelNumber = "CommDeviceSuperFscc422Factory")]
   public class CommDeviceSuperFscc422Factory : IInstrumentFactory
   {
      private readonly List<Type> _supportedInterfaces = new List<Type>();
      private readonly IConfigurationManager _configurationManager;
      private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
      private static string DefaultPath;

      public CommDeviceSuperFscc422Factory(string defaultConfigPath = DefaultConfigPath)
         : this(null, defaultConfigPath)
      {
      }

      /// <summary>
      /// CommDeviceSuperFscc422Factory injection constructor
      /// </summary>
      [ImportingConstructor]
      public CommDeviceSuperFscc422Factory([Import(AllowDefault = false)] IConfigurationManager configManager,
                                 [Import(AllowDefault = true)] string defaultConfigPath = null)
      {
         DefaultPath = defaultConfigPath;

         if (LogManager.Configuration == null)
         {
            var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
         }

         _configurationManager = configManager ?? GetConfigurationManager();
         _supportedInterfaces.Add(typeof(ICommDevice));
      }
      /// <summary>
      /// Gets the instrument
      /// </summary>
      /// <param name="name"></param>
      /// <returns></returns>
      public IInstrument GetInstrument(string name)
      {
         try
         {
            return new CommDeviceSuperFscc422(name, _configurationManager);
         }
         catch (Exception)
         {
            throw;
         }
      }

      /// <summary>
      /// Gets the instrument
      /// </summary>
      /// <param name="name"></param>
      /// <returns></returns>
      public object GetInstrument(string name, bool simulateHw)
      {
         try
         {
            if (simulateHw)
               return new CommDeviceSim(name, _configurationManager);
            else
               return new CommDeviceSuperFscc422(name, _configurationManager);
         }
         catch (Exception)
         {
            throw;
         }
      }

      /// <summary>
      /// Gets supported interfaces
      /// </summary>
      /// <returns></returns>
      public ICollection<Type> GetSupportedInterfaces()
      {
         return _supportedInterfaces.ToArray();
      }

      /// <summary>
      /// returns configuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
      /// </summary>
      /// <returns></returns>
      private static IConfigurationManager GetConfigurationManager()
      {
         return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
      }

      /// <summary>
      /// 
      /// </summary>
      /// <param name="instrumentDefFile"></param>
      /// <param name="iniSectionName"></param>
      /// <param name="isThereHardware"></param>
      /// <returns></returns>
      public static ICommDevice CreateFastCommDevice(string instrumentDefFile, string iniSectionName, bool isThereHardware)
      {
         const string FAST_COMM_FSCC = "FAST_COMM_FSCC";

         IniFile iniReader = new IniFile(instrumentDefFile);

         bool shallWeDebug = Convert.ToBoolean(iniReader.ReadValue(FAST_COMM_FSCC, "SHALL_WE_DEBUG"));
         uint port = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "PORT"));
         uint clock = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "CLOCK_FREQUENCY"), 16);
         uint bgr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "BGR_REGISTER"), 16);
         uint ccr0 = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "CCR0_REGISTER"), 16);
         uint ccr0Reset = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "CCR0_SOF_RESET_VALUE"), 16);
         uint ccr1 = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "CCR1_REGISTER"), 16);
         uint ccr2 = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "CCR2_REGISTER"), 16);
         uint dpllr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "DPLLR_REGISTER"), 16);
         uint fcr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "FCR_REGISTER"), 16);
         uint fifot = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "FIFO_T_REGISTER"), 16);
         uint imr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "IMR_REGISTER"), 16);
         uint ppr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "PPR_REGISTER"), 16);
         uint ramr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "RAMR_REGISTER"), 16);
         uint rar = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "RAR_REGISTER"), 16);
         uint smr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "SMR_REGISTER"), 16);
         uint ssr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "SSR_REGISTER"), 16);
         uint tcr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "TCR_REGISTER"), 16);
         uint tmr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "TMR_REGISTER"), 16);
         uint tsr = Convert.ToUInt32(iniReader.ReadValue(FAST_COMM_FSCC, "TSR_REGISTER"), 16);

         bool shallWeReceiveMultiple = true;
         bool shallWeAppendStatus = false;

         if (shallWeDebug == true)
         {
            shallWeReceiveMultiple = false;
            shallWeAppendStatus = true;
         }

         if (isThereHardware == true)
         {
            return new CommDeviceSuperFscc422(iniSectionName, port, clock, shallWeReceiveMultiple, shallWeAppendStatus, bgr, ccr0, ccr0Reset, ccr1, ccr2, dpllr, fcr, fifot, imr, ppr, ramr, rar, smr, ssr, tcr, tmr, tsr);
         }
         else
         {
            return new CommDeviceSim(iniSectionName);
         }
      }

   }
}