using System;
using System.Collections.Generic;

namespace AteSystems.InCal
{
   /// <summary>
   /// Used by the interface function AmbFilename to specify the type of data contained
   /// in the file as encoded in the filename.
   /// </summary>
   public enum EAbSplitFileType
   {
       MeasuredThru,
       DeembedA,
       DeembedB
   }

   /// <summary>
   /// Used by the interface function AmbFilename to specify the type of data contained
   /// in the file as encoded in the filename.
   /// </summary>
   public enum EAmbFileType
   {
       MeasuredShort,
       MeasuredThru,
       DeembedA,
       DeembedB,
       DeembedM
   }

   /// <summary>
   /// Used by the interface function AmbMeasure to specify the type of measurement
   /// being made.
   /// </summary>
   public enum EAmbMeasureType
   {
       Short,
       Thru,
   }

   /// <summary>
   /// Enumerates the different configurations that can be defined.
   /// </summary>
   public enum EConfigType
   {
       Unknown,
       AbSplit,
       AmbSplit,
       Calibration,
       Dcm,
       Fcm,
       MultiSwitch,
       Path,
       Pna,
       PowerBridge,
       Sequence,
       Scm,
       ShortOpenLoad,
       Switch,
       UserDevice,
       // the following configuration types are for internal use only and should not
       // be used.
       _RfhMotion_,
       _SmcMotion_,
   }

   /// <summary>
   /// Used by the interface function SolFilename to specify the type of data contained
   /// in the file as encoded in the filename.
   /// </summary>
   public enum ESolFileType
   {
       Characterized,
       Measured,
       Deembed,
   }

   /// <summary>
   /// Used by the interface ShortOpenLoad functions to specify the type of measurement
   /// being made or the data stored form the specified measurment type.
   /// </summary>
   public enum ESolMeasureType
   {
       Short,
       Open,
       Load,
   }

   public interface IApi
   {
       #region Events

       /// <summary>
       /// Published event for every command that is sent to a device in the course
       /// of a calibration.
       /// </summary>
       event CommandEvent CommandEvent;

       /// <summary>
       /// Published event for every error occurance during a calibration. This can
       /// be used to get calibration errors in a more timely manner than querying
       /// at the end of a calibration return.
       /// </summary>
       event ErrorEvent ErrorEvent;

       #endregion Events

       #region Properties

       /// <summary>
       /// Gets or sets whether exceptions thrown during the course of a calibration
       /// are caught and turned into error strings that can be queried.
       /// </summary>
       bool CatchExceptions { get; set; }

       #endregion Properties

       #region Methods

       /// <summary>Aborts a running named calibration.</summary>
       /// <param name="name">The name of the calibration or sequence from the configuration file.</param>
       void Abort(string name);

       /// <summary>
       /// Abort all running calibrations.
       /// Can be used when the name of the calibration is unknown.
       /// </summary>
       void AbortAll();

       /// <summary>Calculate the AB Split de-embed file as specified in the named configuration.</summary>
       /// <param name="abSplitName">The name or alias of the AB Split configuration.</param>
       /// <param name="pnaName">The name of the PNA config section that will be performing the measurement.</param>
       /// <returns>True on success.</returns>
       bool AbSplitCalculate(string abSplitName, string pnaName);

       /// <summary>
       /// Gets the filename that would be created by an AMB calculation or measurement.
       /// </summary>
       /// <param name="abSplitName">The name of the AB configuration section.</param>
       /// <param name="abSplitFileType">The AMB file type that will be created.</param>
       /// <returns>The filename that will be used.</returns>
       string AbSplitFilename(string abSplitName, EAbSplitFileType abSplitFileType);

       /// <summary>Calculate the AMB Split de-embed file as specified in the named configuration.</summary>
       /// <param name="ambName">The name or alias of the AMB Split configuration.</param>
       /// <returns>True on success.</returns>
       bool AmbCalculate(string ambName);

       /// <summary>
       /// Gets the filename that would be created by an AMB calculation or measurement.
       /// </summary>
       /// <param name="ambName">The name of the AMB configuration section.</param>
       /// <param name="ambFileType">The AMB file type that will be created.</param>
       /// <returns>The filename that will be used.</returns>
       string AmbFilename(string ambName, EAmbFileType ambFileType);

       /// <summary>
       /// Execute an AMB measurement.
       /// </summary>
       /// <param name="ambName">The name of the AMB config section.</param>
       /// <param name="pnaName">The name of the PNA config section that will be performing the measurement.</param>
       /// <param name="measureType">The type of AMB measurement being performed.</param>
       /// <returns>True on success.</returns>
       bool AmbMeasure(string ambName, string pnaName, EAmbMeasureType measureType);

       /// <summary>
       /// Execute a calibration as defined in the configuration on the specified PNA.
       /// </summary>
       /// <param name="calName">The name of the calibration config section that defines the calibration.</param>
       /// <param name="pnaName">The name of the PNA config section that will be performing the calibration.</param>
       /// <returns>True on success.</returns>
       bool Calibrate(string calName, string pnaName);

       /// <summary>
       /// Test call to validate if Dll chain is being called and accesible
       /// </summary>
       bool DllTest();

       /// <summary>
       /// Get a list of config section names based on a key in the config section.
       /// </summary>
       /// <param name="keyName">The name of the key.</param>
       /// <param name="keyValue">The value the key must have to be added to the list.</param>
       /// <returns>A list of strings of the section names found.</returns>
       IList<string> GetConfigStrListByKey(string keyName, string keyValue);

       /// <summary>
       /// Get a list of config section names of that are of a certain config type.
       /// </summary>
       /// <param name="configType">The config type being sought.</param>
       /// <returns>A list of strings of the section names found that are of the config type.</returns>
       IList<string> GetConfigStrListByType(EConfigType configType);

       /// <summary>
       /// Gets the list of error messages that currently have been generated since
       /// the last call to this method.
       /// </summary>
       /// <returns>The error messages as a list  of strings.</returns>
       IList<string> GetErrorMessageList();

       /// <summary>
       /// Modify or add a key value in the configuration INI file.
       /// If the key does not exist it will be created.
       /// The ini file is saved when the function completes.
       /// </summary>
       /// <param name="sectionName">The section name the key is under.</param>
       /// <param name="keyName">The name of the key.</param>
       /// <param name="keyValue">The value associated with the key.</param>
       /// <param name="keyComment">The comment to place before the key/value int he INI file.</param>
       /// <returns>True on success.</returns>
       bool IniFileModifyKey(string sectionName, string keyName, string keyValue, string keyComment);

       /// <summary>
       /// Read a key value from the INI configuration file.
       /// </summary>
       /// <param name="sectionName">The sectionthe key is located under.</param>
       /// <param name="keyName">The name of the key.</param>
       /// <returns>The value of the key.
       /// This will return an empty string if the key does not exist or the value is not defined in the file.</returns>
       string IniFileReadKey(string sectionName, string keyName);

       /// <summary>
       /// Initialize the calibration library by loading in a configuration file.
       /// </summary>
       /// <param name="configFilename">The name of the configuration file.</param>
       /// <returns>True on success.</returns>
       bool Initialize(string configFilename);

       /// <summary>
       /// Execute a calibration as defined in the configuration on the specified PNA.
       /// </summary>
       /// <param name="calName">The name of the calibration config section that defines the calibration.</param>
       /// <param name="pnaName">The name of the PNA config section that will be performing the calibration.</param>
       /// <returns>True on success.</returns>
       bool LogCalibrate(string calName, string pnaName, string logFilename = null);

       /// <summary>
       /// Run a sequence that is defined in the configuration file and log the command events.
       /// </summary>
       /// <param name="seqName">The name of the sequence section in the file.</param>
       /// <param name="logFilename">The name of the log file to write</param>
       /// <returns>True on success.</returns>
       bool LogSequence(string seqName, string logFilename = null);

       /// <summary>
       /// Run a sequence that is defined in the configuration file.
       /// </summary>
       /// <param name="seqName">The name of the sequence section in the file.</param>
       /// <returns>True on success.</returns>
       bool RunSequence(string seqName);

       /// <summary>
       /// Send a SCPI string to a device defined in the configuration file.
       /// </summary>
       /// <param name="name">The alias (section name) defining the device in the configuration file.</param>
       /// <param name="command">The SCPI command to send to the device.</param>
       /// <param name="responseTimeout">The time to wait before issuing a timeout error.</param>
       /// <returns>The response string.</returns>
       string SendScpi(string name, string command, TimeSpan? responseTimeout = null);

       /// <summary>
       /// Send a string to a user device defined in the configuration file.
       /// </summary>
       /// <param name="name">The alias (section name) defining the device in the configuration file.</param>
       /// <param name="data">The string to send to the device.</param>
       /// <param name="waitForResponse">If true always waits for a response, if false uses 'WaitForAck' property.</param>
       /// <param name="responseTimeout">The time to wait before issuing a timeout error.</param>
       /// <returns>The response string.</returns>
       string SendToUserDevice(string name, string data, bool waitForResponse, TimeSpan? responseTimeout = null);

       /// <summary>
       /// Set the path as defined by a Path section in the configuration file.
       /// </summary>
       /// <param name="pathName">The name of the Path section in the configuration file.</param>
       /// <returns>True on success.</returns>
       bool SetPath(string pathName);

       /// <summary>
       /// Calculate the De-embed values based on the short open load measurements performed previously.
       /// </summary>
       /// <param name="solName">The name of the Short Open Load scetion in the configuration file.</param>
       /// <returns>True on success.</returns>
       bool SolCalculate(string solName);

       /// <summary>
       /// Get teh name of the file that will be created by a Short Open Load measurement or calculation.
       /// </summary>
       /// <param name="solName">The name of the Short Open Load scetion in the configuration file.</param>
       /// <param name="port">The PNA port of the measurement.</param>
       /// <param name="solFileType">The type of file whose name is sought.</param>
       /// <param name="measureType">The measurement type of the file. For De-embed file types this parameter is ignored.</param>
       /// <returns></returns>
       string SolFilename(string solName, int port, ESolFileType solFileType, ESolMeasureType measureType);

       /// <summary>
       /// Perform a Short Open or Load measurment as defined in a Short Open Load section of the configuration file.
       /// </summary>
       /// <param name="solName">The name of the Short Open Load scetion in the configuration file.</param>
       /// <param name="pnaName">The name of the PNA section defining the PNA to use in the measurement.</param>
       /// <param name="measureType">The type of measurement to be made (Short, Open or Load).</param>
       /// <returns>True on success.</returns>
       bool SolMeasure(string solName, string pnaName, ESolMeasureType measureType);

       /// <summary>
       /// Subscribe to an error events that may occur.
       /// This method is provided to make the API compatible with the WIN32 API
       /// </summary>
       /// <param name="eventHandler">The event handler to be called.</param>
       /// <param name="subscribe">True if subscribing or false if unsubscribing.</param>
       void SubscribeToErrorEvents(ErrorEvent eventHandler, bool subscribe);

       /// <summary>
       /// Subscribe to an configuration component events that may occur.
       /// Any action taken based on a configuraiton component creates a command event.
       /// i.e SetPath, Calibrate, SendScpi and so on.
       /// This method is provided to make the API compatible with the WIN32 API
       /// </summary>
       /// <param name="eventHandler">The event handler to be called.</param>
       /// <param name="subscribe">True if subscribing or false if unsubscribing.</param>
       void SubscribeToScpiCommandEvents(CommandEvent eventHandler, bool subscribe);

       #endregion Methods
   }

   /// <summary>
   /// The event handler type for component command events.
   /// Event handlers subscribing to command events need to have this signature
   /// and expect the defined parameter list.
   /// </summary>
   /// <param name="eventId">The Event ID, used to identify the event if an update event is published.</param>
   /// <param name="senderName">The name of the component that is processing a command.</param>
   /// <param name="eventDescription">The event description.</param>
   /// <param name="detailStr">Any relevent details of the event.</param>
   /// <param name="updateFlag">Set to true if this event is updating information of a previous event.</param>
   public delegate void CommandEvent(int eventId, string senderName, string eventDescription, string detailStr, bool updateFlag);

   /// <summary>
   /// The event handler type for execution error events.
   /// Event handlers subscribing to error events need to have this signature
   /// and expect the defined parameter list.
   /// </summary>
   /// <param name="error">The error that occured</param>
   public delegate void ErrorEvent(string error);
}