using System;
using System.Threading;
using DebugToolInstrumentInterface;

namespace SimpleSpectrumAnalyzer;

[SupportedResourceName("RS_FS")]
[SupportedResourceName("Agilent_8960")]
[SupportedResourceName("HP_85XX")]
[SupportedResourceName("Adventest_R3267")]
[SupportedResourceName("QTI_SCPI")]
[SupportedResourceName("Agilent_SpecAn")]
public class SA : ISpectrumAnalyzer, Instrument, IDisposable
{
	private enum SAType
	{
		Agilent_SpecAn,
		Agilent_8960,
		RS_FS,
		HP_85XX,
		Adventest_R3267,
		QTI_SCPI,
		Unknown
	}

	private Technology m_Technology = Technology.NONE;

	private string msg;

	private double QTI_SCPI_Ver;

	private bool PowerMeas;

	private SAType sa = SAType.Unknown;

	private TE_Handle te_handle;

	private string m_resourceString;

	public void Dispose()
	{
	}

	public void setupTEDriverType(TEDriverType type)
	{
		te_handle.SetupDriverType(type);
	}

	public SA()
	{
		te_handle = new TE_Handle();
	}

	public bool Setup(string resourceString)
	{
		try
		{
			string[] array = resourceString.Split(',');
			m_resourceString = array[0];
			if (array[0] == "Agilent_SpecAn")
			{
				sa = SAType.Agilent_SpecAn;
			}
			else if (array[0] == "HP_85XX")
			{
				sa = SAType.HP_85XX;
			}
			else if (array[0] == "Advantest_R3267")
			{
				sa = SAType.Adventest_R3267;
			}
			else if (array[0] == "RS_FS")
			{
				sa = SAType.RS_FS;
			}
			else if (array[0] == "QTI_SCPI")
			{
				sa = SAType.QTI_SCPI;
			}
			else if (array[0] == "Agilent_8960")
			{
				sa = SAType.Agilent_8960;
			}
			else
			{
				sa = SAType.Unknown;
			}
			return te_handle.Init(array[1]);
		}
		catch
		{
			return false;
		}
	}

	public void Close()
	{
		te_handle.Close();
	}

	public string GetResourceString()
	{
		return m_resourceString;
	}

	public void SetCenterFrequency(double dFrequencyMHz)
	{
		msg = "";
		if (sa == SAType.Agilent_SpecAn)
		{
			msg = ":FREQ:CENT " + dFrequencyMHz + "MHZ";
		}
		else if (sa == SAType.Adventest_R3267)
		{
			msg = "CF " + dFrequencyMHz + "MZ";
		}
		else if (sa == SAType.HP_85XX)
		{
			msg = "CF " + dFrequencyMHz + "MHZ";
		}
		else if (sa == SAType.RS_FS)
		{
			msg = "FREQ:CENT " + dFrequencyMHz + "MHz";
		}
		else if (sa == SAType.QTI_SCPI)
		{
			msg = "QCOM:SENS:FREQ:CENT " + dFrequencyMHz + "MHz";
		}
		else if (sa == SAType.Agilent_8960)
		{
			if (m_Technology != 0 && m_Technology != Technology.GSM && m_Technology != Technology.WCDMA)
			{
				return;
			}
			te_handle.write("RFANalyzer:CONTrol:MEASurement:FREQuency:AUTO OFF");
			msg = "RFANALYZER:MANUAL:MEASUREMENT:MFREQUENCY " + dFrequencyMHz + " MHZ";
		}
		te_handle.write(msg);
	}

	public void SetSpan(double dFrequencyMHz)
	{
		msg = "";
		if (sa == SAType.Agilent_SpecAn)
		{
			msg = ":FREQ:SPAN " + dFrequencyMHz + "MHZ";
		}
		else if (sa == SAType.Adventest_R3267)
		{
			msg = "SP " + dFrequencyMHz + "MZ";
		}
		else if (sa == SAType.HP_85XX)
		{
			msg = "SP " + dFrequencyMHz + "MHZ";
		}
		else if (sa == SAType.RS_FS)
		{
			msg = "FREQ:SPAN " + dFrequencyMHz + "MHz";
		}
		else if (sa == SAType.QTI_SCPI)
		{
			if (dFrequencyMHz == 0.1)
			{
				SetFilter(Filter.Bandwidth_100kHz);
				return;
			}
			if (dFrequencyMHz == 3.0)
			{
				SetFilter(Filter.Bandwidth_3MHz);
				return;
			}
			if (dFrequencyMHz == 5.0)
			{
				SetFilter(Filter.Bandwidth_5MHz);
				return;
			}
			if (dFrequencyMHz == 10.0)
			{
				SetFilter(Filter.Bandwidth_10MHz);
				return;
			}
			if (dFrequencyMHz == 15.0)
			{
				SetFilter(Filter.Bandwidth_15MHz);
				return;
			}
			if (dFrequencyMHz == 20.0)
			{
				SetFilter(Filter.Bandwidth_20MHz);
				return;
			}
		}
		else if (sa == SAType.Agilent_8960)
		{
			return;
		}
		te_handle.write(msg);
	}

	public void SetReferenceLevel(double dRefLeveldBm)
	{
		msg = "";
		if (sa == SAType.Agilent_SpecAn)
		{
			msg = ":DISP:WIND:TRAC:Y:RLEV " + dRefLeveldBm;
		}
		else if (sa == SAType.Adventest_R3267)
		{
			msg = "RL " + dRefLeveldBm + "DBM";
		}
		else if (sa == SAType.HP_85XX)
		{
			msg = "RL " + dRefLeveldBm + "DM";
		}
		else if (sa == SAType.RS_FS)
		{
			msg = "DISP:WIND:TRAC:RLEV " + dRefLeveldBm;
		}
		else if (sa == SAType.QTI_SCPI)
		{
			if (QTI_SCPI_Ver == 0.0)
			{
				QTI_SCPI_Ver = Convert.ToDouble(GetQTI_SCPIVersion());
			}
			if (QTI_SCPI_Ver < 1.7)
			{
				msg = "QCOM:SENS:RLEV " + dRefLeveldBm;
			}
			else
			{
				msg = "QCOM:SENS:POW:REF:LEV " + dRefLeveldBm;
			}
		}
		else if (sa == SAType.Agilent_8960)
		{
			if (m_Technology == Technology.GSM)
			{
				msg = "SETup:TXPower:RANGe:AUTO ON";
			}
			else if (m_Technology == Technology.CDMA)
			{
				te_handle.write("RFANALYZER:CONTROL:POWER:AUTO OFF");
				msg = "RFANALYZER:MANUAL:POWER:SELECTED " + dRefLeveldBm + " DBM";
			}
			else
			{
				if (m_Technology != Technology.WCDMA)
				{
					return;
				}
				te_handle.write("SETup:WCPower:RANGe:AUTO OFF");
				msg = "SETup:WCPower:POWer:RANGe:OFFSet:MANual " + dRefLeveldBm;
			}
		}
		te_handle.write(msg);
	}

	private void SetFilter(Filter filter)
	{
		msg = "";
		if (sa == SAType.QTI_SCPI)
		{
			if (QTI_SCPI_Ver == 0.0)
			{
				QTI_SCPI_Ver = Convert.ToDouble(GetQTI_SCPIVersion());
			}
			if (QTI_SCPI_Ver < 1.5)
			{
				switch (filter)
				{
				case Filter.Bandwidth_100kHz:
					msg = "QCOM:SENS:FILT:TYPE Gaussian_100kHZ";
					break;
				case Filter.Bandwidth_3MHz:
					msg = "QCOM:SENS:FILT:TYPE BANDPASS_3MHz";
					break;
				case Filter.Bandwidth_5MHz:
					msg = "QCOM:SENS:FILT:TYPE BANDPASS_5MHz";
					break;
				case Filter.Bandwidth_10MHz:
					msg = "QCOM:SENS:FILT:TYPE BANDPASS_10MHz";
					break;
				case Filter.Bandwidth_15MHz:
					msg = "QCOM:SENS:FILT:TYPE BANDPASS_15MHz";
					break;
				case Filter.Bandwidth_20MHz:
					msg = "QCOM:SENS:FILT:TYPE BANDPASS_20MHz";
					break;
				}
			}
			else
			{
				switch (filter)
				{
				case Filter.Bandwidth_100kHz:
					msg = "QCOM:SENS:FILT:TYPE 'Gaussian_100kHZ'";
					break;
				case Filter.Bandwidth_3MHz:
					msg = "QCOM:SENS:FILT:TYPE 'BANDPASS_3MHz'";
					break;
				case Filter.Bandwidth_5MHz:
					msg = "QCOM:SENS:FILT:TYPE 'BANDPASS_5MHz'";
					break;
				case Filter.Bandwidth_10MHz:
					msg = "QCOM:SENS:FILT:TYPE 'BANDPASS_10MHz'";
					break;
				case Filter.Bandwidth_15MHz:
					msg = "QCOM:SENS:FILT:TYPE 'BANDPASS_15MHz'";
					break;
				case Filter.Bandwidth_20MHz:
					msg = "QCOM:SENS:FILT:TYPE 'BANDPASS_20MHz'";
					break;
				}
			}
		}
		te_handle.write(msg);
	}

	public string GetPower()
	{
		string text = "";
		msg = "";
		if (sa == SAType.QTI_SCPI)
		{
			QTI_SCPI_Ver = Convert.ToDouble(GetQTI_SCPIVersion());
			if (!(QTI_SCPI_Ver > 1.5))
			{
				return "QSCPI too old";
			}
			te_handle.write("QCOM:INIT:SENSe:POWer;");
			Thread.Sleep(200);
			msg = "QCOM:FETC:SENS:POW?";
		}
		else
		{
			if (sa != SAType.Agilent_8960)
			{
				return "Not a valid spectrum analyzer";
			}
			if (m_Technology == Technology.WCDMA)
			{
				te_handle.write("INITiate:WCPower");
				msg = "FETCh:WCPOWER?";
			}
			else if (m_Technology == Technology.CDMA)
			{
				te_handle.write("INITiate:CPower");
				msg = "FETCh:CPower?";
			}
			else
			{
				if (m_Technology != Technology.GSM)
				{
					return "Not Valid";
				}
				te_handle.write("INITiate:TXPower");
				msg = "FETCh:TXPower?";
			}
		}
		PowerMeas = true;
		text = GetResult(msg);
		PowerMeas = false;
		return InterpretResults(text);
	}

	public bool SetPathLoss(double dFrequencyMHz, double dLossindB, string TableName)
	{
		msg = "";
		string cmd = "";
		bool flag = false;
		if (sa == SAType.QTI_SCPI)
		{
			string result = GetResult("QCOM:MMEM:DIR:CORRection? '" + TableName + "'");
			try
			{
				if (Convert.ToDouble(result) == 1.0)
				{
					flag = true;
				}
			}
			catch (Exception)
			{
				string text = result.Substring(0, 2);
				text = text.ToUpper();
				if (text != "NO")
				{
					flag = true;
				}
			}
			if (flag)
			{
				msg = "QCOM:MMEM:ADD:CORRection '" + TableName + "'," + dFrequencyMHz + "MHz," + dLossindB;
			}
			else
			{
				msg = "QCOM:MMEM:STORe:CORRection '" + TableName + "'";
				cmd = "QCOM:MMEM:ADD:CORRection '" + TableName + "'," + dFrequencyMHz + "MHz," + dLossindB;
			}
		}
		else
		{
			if (sa != SAType.Agilent_8960)
			{
				return false;
			}
			msg = "SYSTEM:CORRECTION:SFREQUENCY " + dFrequencyMHz + " MHZ";
			cmd = "SYSTEM:CORRECTION:SGAIN " + dLossindB;
		}
		te_handle.write(msg);
		te_handle.write(cmd);
		return true;
	}

	public void SetPathLoss(string TableName, string RFPort, string DUT)
	{
		msg = "";
		if (sa == SAType.QTI_SCPI)
		{
			msg = "QCOM:SENSe:CORRection '" + TableName + "'," + RFPort + "," + DUT;
		}
		else if (sa == SAType.Agilent_8960)
		{
			msg = "SYSTEM:CORRECTION:STATE ON";
		}
		te_handle.write(msg);
	}

	public string GetDriverVersion()
	{
		return typeof(SA).Assembly.GetName().Version.ToString();
	}

	private string GetQTI_SCPIVersion()
	{
		if (sa == SAType.QTI_SCPI)
		{
			return GetResult("QCOM:SYSTem:VERSION?");
		}
		return "";
	}

	private string GetResult(string query)
	{
		string retStr = "";
		te_handle.write(query);
		if (PowerMeas)
		{
			Thread.Sleep(500);
		}
		te_handle.read(out retStr);
		return retStr;
	}

	private string InterpretResults(string result)
	{
		try
		{
			string[] array = result.Split(',');
			if (sa == SAType.Agilent_8960)
			{
				if (array[0] == "0" || array[0] == "+0")
				{
					return double.Parse(array[1]).ToString("#.##");
				}
				if (array[0] == "+2")
				{
					return "Measurement timeout";
				}
				if (array[0] == "+5")
				{
					return "Over Range";
				}
				if (array[0] == "+6")
				{
					return "Under Range";
				}
				if (array[0] == "+13")
				{
					return "Unidentified Error";
				}
				if (array[0] == "+21")
				{
					return "Parameter Error";
				}
				return "Unknown Error";
			}
			if (sa == SAType.QTI_SCPI)
			{
				if (array[0] == "0" || array[0] == "+0")
				{
					return double.Parse(array[1]).ToString("#.##");
				}
				if (array[0] == "-1")
				{
					return "Error not defined";
				}
				if (array[0] == "1")
				{
					return "Trigger failure";
				}
				if (array[0] == "2")
				{
					return "Over Range";
				}
				if (array[0] == "3")
				{
					return "Under Range";
				}
				return "Unknown Error";
			}
			return "000";
		}
		catch
		{
			return "000";
		}
	}

	public bool IsCalTableSupported()
	{
		if (sa == SAType.QTI_SCPI)
		{
			return true;
		}
		if (sa == SAType.Agilent_8960)
		{
			return true;
		}
		return false;
	}

	public bool IsGetPowerSupported()
	{
		if (sa == SAType.QTI_SCPI)
		{
			return true;
		}
		if (sa == SAType.Agilent_8960)
		{
			return true;
		}
		return false;
	}

	public void SetupMeasurement(Technology tech)
	{
		msg = "";
		string cmd = "";
		m_Technology = tech;
		if (sa == SAType.QTI_SCPI)
		{
			msg = "SYSTEM:PRESET";
			cmd = "*CLS";
		}
		else
		{
			if (sa != SAType.Agilent_8960)
			{
				return;
			}
			te_handle.write("*CLS");
			if (m_Technology == Technology.WCDMA)
			{
				msg = "SYSTem:APPLication:FORMat 'WCDMA'";
				cmd = "CALL:OPERating:MODE FDDTest";
			}
			else if (m_Technology == Technology.GSM)
			{
				msg = "SYSTem:APPLication:FORMat 'GSM'";
				cmd = "CALL:OPERating:MODE CALL";
			}
			else if (m_Technology == Technology.CDMA)
			{
				msg = "SYSTem:APPLication:FORMat 'IS-2000/IS-95/AMPS'";
				cmd = "Call:OPERating:MODE CALL";
			}
			else
			{
				if (m_Technology == Technology.TDSCDMA)
				{
					msg = "";
					cmd = "";
					return;
				}
				if (m_Technology == Technology.LTE)
				{
					msg = "";
					cmd = "";
					return;
				}
			}
		}
		te_handle.write(msg);
		te_handle.write(cmd);
	}

	public void SetTriggerType(TriggerType trigger)
	{
		msg = "";
		if (sa == SAType.QTI_SCPI)
		{
			switch (trigger)
			{
			case TriggerType.FREE:
				msg = "QCOM:SENSe:TRIGger:TYPE FREE";
				break;
			case TriggerType.IF:
				msg = "QCOM:SENSe:TRIGger:TYPE IF";
				break;
			case TriggerType.SOURCE_LM:
				msg = "QCOM:SENSe:TRIGger:TYPE SOURCE_LM";
				break;
			}
		}
		te_handle.write(msg);
	}
}
