using System;
using System.Runtime.InteropServices;
using System.Text;

namespace QC.VISA;

public class Visa32
{
	private const int VI_NULL = 0;

	private const int VI_TRUE = 1;

	private const int VI_FALSE = 0;

	private const int VI_SUCCESS = 0;

	private const int VI_SUCCESS_TERM_CHAR = 1073676293;

	private const int VI_SUCCESS_MAX_CNT = 1073676294;

	private const int VI_WARN_NULL_OBJECT = 1073676418;

	private const int VI_READ_BUF = 1;

	private const int VI_WRITE_BUF = 2;

	private const int VI_READ_BUF_DISCARD = 4;

	private const int VI_WRITE_BUF_DISCARD = 8;

	private const int VI_IO_IN_BUF = 16;

	private const int VI_IO_OUT_BUF = 32;

	private const int VI_IO_IN_BUF_DISCARD = 64;

	private const int VI_IO_OUT_BUF_DISCARD = 128;

	private const int VI_ATTR_SEND_END_EN = 1073676310;

	private const int VI_ATTR_TERMCHAR = 1073676312;

	private const int VI_ATTR_TMO_VALUE = 1073676314;

	private const int VI_ATTR_TERMCHAR_EN = 1073676344;

	private const uint VI_ATTR_RD_BUF_OPER_MODE = 1073676330u;

	private const uint VI_ATTR_WR_BUF_OPER_MODE = 1073676333u;

	private const int VI_FLUSH_ON_ACCESS = 1;

	private const int VI_FLUSH_WHEN_FULL = 2;

	private const int VI_FLUSH_DISABLE = 3;

	private uint resourceManagerSession;

	private uint instrumentSession;

	private string resource;

	private int timeoutMilliseconds = 10000;

	public static string DEBUG_FILE_NAME = "c:\\temp\\VISA_DEBUG.TXT";

	public string Resource
	{
		get
		{
			return resource;
		}
		set
		{
			resource = value;
		}
	}

	public TimeSpan IOTimeout
	{
		get
		{
			if (instrumentSession != 0)
			{
				uint attributeValue = 0u;
				int num = viGetAttribute(instrumentSession, 1073676314u, ref attributeValue);
				if (num != 0)
				{
					Exception ex = new Exception("viGetAttribute() error: " + GetStatusCodeDescription(num));
					throw ex;
				}
				timeoutMilliseconds = (int)attributeValue;
			}
			return new TimeSpan(0, 0, 0, 0, timeoutMilliseconds);
		}
		set
		{
			timeoutMilliseconds = (int)value.TotalMilliseconds;
			if (instrumentSession != 0)
			{
				int num = viSetAttribute(instrumentSession, 1073676314u, (uint)timeoutMilliseconds);
				if (num != 0)
				{
					Exception ex = new Exception("viSetAttribute() error: " + GetStatusCodeDescription(num));
					throw ex;
				}
			}
		}
	}

	[DllImport("Visa32.dll")]
	private static extern int viClose(uint session);

	[DllImport("Visa32.dll")]
	private static extern int viGetAttribute(uint instrumentSession, uint attributeName, ref uint attributeValue);

	[DllImport("Visa32.dll")]
	private static extern int viOpen(uint resourceManagerSession, string resourceName, uint accessMode, uint openTimeout, ref uint instrumentSession);

	[DllImport("Visa32.dll")]
	private static extern int viOpenDefaultRM(ref uint resourceManagerSession);

	[DllImport("Visa32.dll")]
	private static extern int viRead(uint instrumentSession, [Out] byte[] dataRead, uint numberOfBytesToRead, ref uint numberOfBytesRead);

	[DllImport("Visa32.dll")]
	private static extern int viSetAttribute(uint instrumentSession, uint attributeName, uint attributeValue);

	[DllImport("Visa32.dll")]
	private static extern int viWrite(uint instrumentSession, byte[] dataToWrite, uint numberOfBytesToWrite, ref uint numberOfBytesWritten);

	[DllImport("Visa32.dll")]
	private static extern int viStatusDesc(uint instrumentSession, uint statusCode, [Out] byte[] statusCodeDescription);

	public static void DebugWrite(string str)
	{
	}

	public byte[] Read(int count)
	{
		byte[] array = new byte[count];
		uint numberOfBytesRead = 0u;
		try
		{
			if (count < 1)
			{
				return new byte[0];
			}
			if (!IsOpen())
			{
				Open();
			}
			int num = viRead(instrumentSession, array, (uint)count, ref numberOfBytesRead);
			if (num != 0 && num != 1073676294 && num != 1073676293)
			{
				throw new Exception("viRead() error: " + GetStatusCodeDescription(num));
			}
			byte[] array2 = new byte[numberOfBytesRead];
			Array.Copy(array, array2, numberOfBytesRead);
			return array2;
		}
		catch (Exception ex)
		{
			if (numberOfBytesRead == 0)
			{
				viClose(instrumentSession);
				instrumentSession = 0u;
				viClose(resourceManagerSession);
				resourceManagerSession = 0u;
				ex.Source = "Read " + ex.Source;
				throw ex;
			}
			byte[] array2 = new byte[numberOfBytesRead];
			Array.Copy(array, array2, numberOfBytesRead);
			return array2;
		}
	}

	public byte ReadByte()
	{
		try
		{
			if (!IsOpen())
			{
				Open();
			}
			byte[] array = new byte[1];
			uint numberOfBytesRead = 0u;
			int num = viRead(instrumentSession, array, 1u, ref numberOfBytesRead);
			if (num != 0 && num != 1073676294 && num != 1073676293)
			{
				throw new Exception("viRead() error: " + GetStatusCodeDescription(num));
			}
			return array[0];
		}
		catch (Exception ex)
		{
			viClose(instrumentSession);
			instrumentSession = 0u;
			viClose(resourceManagerSession);
			resourceManagerSession = 0u;
			ex.Source = "ReadByte " + ex.Source;
			throw ex;
		}
	}

	public string ReadString()
	{
		try
		{
			if (!IsOpen())
			{
				Open();
			}
			string text = "";
			int num;
			do
			{
				byte[] array = new byte[256];
				uint numberOfBytesRead = 0u;
				num = viRead(instrumentSession, array, 256u, ref numberOfBytesRead);
				if (num != 0 && num != 1073676294 && num != 1073676293)
				{
					throw new Exception("viRead() error: " + GetStatusCodeDescription(num));
				}
				byte[] array2 = new byte[numberOfBytesRead];
				Array.Copy(array, array2, numberOfBytesRead);
				text += Encoding.ASCII.GetString(array2);
			}
			while (num == 1073676294);
			return text;
		}
		catch (Exception ex)
		{
			viClose(instrumentSession);
			instrumentSession = 0u;
			viClose(resourceManagerSession);
			resourceManagerSession = 0u;
			ex.Source = "ReadString " + ex.Source;
			throw ex;
		}
	}

	public string ReadString(int count)
	{
		try
		{
			if (!IsOpen())
			{
				Open();
			}
			byte[] array = new byte[count];
			uint numberOfBytesRead = 0u;
			int num = viRead(instrumentSession, array, (uint)count, ref numberOfBytesRead);
			if (num != 0 && num != 1073676294 && num != 1073676293)
			{
				throw new Exception("viRead() error: " + GetStatusCodeDescription(num));
			}
			byte[] array2 = new byte[numberOfBytesRead];
			Array.Copy(array, array2, numberOfBytesRead);
			return Encoding.ASCII.GetString(array2);
		}
		catch (Exception ex)
		{
			viClose(instrumentSession);
			instrumentSession = 0u;
			viClose(resourceManagerSession);
			resourceManagerSession = 0u;
			ex.Source = "ReadString " + ex.Source;
			throw ex;
		}
	}

	public void Write(byte[] data)
	{
		DebugWrite("Write");
		try
		{
			if (!IsOpen())
			{
				Open();
			}
			uint numberOfBytesWritten = 0u;
			byte[] array = new byte[data.Length + 1];
			for (int i = 0; i < data.Length; i++)
			{
				array[i] = data[i];
			}
			array[array.Length] = 10;
			int num = viWrite(instrumentSession, array, (uint)array.Length, ref numberOfBytesWritten);
			if (num != 0)
			{
				throw new Exception("viWrite() error: " + GetStatusCodeDescription(num));
			}
		}
		catch (Exception ex)
		{
			viClose(instrumentSession);
			instrumentSession = 0u;
			viClose(resourceManagerSession);
			resourceManagerSession = 0u;
			ex.Source = "Write " + ex.Source;
			throw ex;
		}
	}

	public void WriteByte(byte data)
	{
		try
		{
			if (!IsOpen())
			{
				Open();
			}
			uint numberOfBytesWritten = 0u;
			byte[] array = new byte[1] { data };
			int num = viWrite(instrumentSession, array, (uint)array.Length, ref numberOfBytesWritten);
			if (num != 0)
			{
				throw new Exception("viWrite() error: " + GetStatusCodeDescription(num));
			}
		}
		catch (Exception ex)
		{
			viClose(instrumentSession);
			instrumentSession = 0u;
			viClose(resourceManagerSession);
			resourceManagerSession = 0u;
			ex.Source = "WriteByte " + ex.Source;
			throw ex;
		}
	}

	public void WriteString(string data)
	{
		DebugWrite("WriteString(" + data + ")");
		try
		{
			if (!IsOpen())
			{
				Open();
			}
			uint numberOfBytesWritten = 0u;
			data += "\n";
			byte[] bytes = Encoding.ASCII.GetBytes(ReplaceCommonEscapeSequences(data));
			IOTimeout = new TimeSpan(0, 0, 0, 0, 10000);
			DebugWrite("viWrite (Length" + (uint)bytes.Length + ")Session" + instrumentSession);
			int num = viWrite(instrumentSession, bytes, (uint)bytes.Length, ref numberOfBytesWritten);
			if (num != 0)
			{
				DebugWrite("viWrite() error: " + GetStatusCodeDescription(num) + "InstrumentSession" + instrumentSession);
				throw new Exception("viWrite() error: " + GetStatusCodeDescription(num));
			}
		}
		catch (Exception ex)
		{
			viClose(instrumentSession);
			instrumentSession = 0u;
			viClose(resourceManagerSession);
			resourceManagerSession = 0u;
			ex.Source = "WriteString " + ex.Source;
			throw ex;
		}
	}

	public bool IsOpen()
	{
		bool result = false;
		try
		{
			if (instrumentSession != 0)
			{
				result = true;
			}
		}
		catch (Exception ex)
		{
			ex.Source = "IsOpen " + ex.Source;
			throw ex;
		}
		return result;
	}

	public void Close()
	{
		uint num = 0u;
		uint num2 = 0u;
		try
		{
			if (instrumentSession != 0)
			{
				num = instrumentSession;
				instrumentSession = 0u;
				int num3 = viClose(num);
				if (num3 != 0 && num3 != 1073676418)
				{
					throw new Exception("viClose(instrumentSessionToClose) error: " + GetStatusCodeDescription(num3));
				}
			}
			if (resourceManagerSession != 0)
			{
				num2 = resourceManagerSession;
				resourceManagerSession = 0u;
				int num4 = viClose(num2);
				if (num4 != 0 && num4 != 1073676418)
				{
					throw new Exception("viClose(resourceManagerSessionToClose) error: " + GetStatusCodeDescription(num4));
				}
			}
		}
		catch (Exception ex)
		{
			ex.Source = "Close " + ex.Source;
			throw ex;
		}
	}

	public void Open()
	{
		DebugWrite("Open");
		try
		{
			Close();
		}
		catch (Exception ex)
		{
			ex.Source = "Open " + ex.Source;
			throw ex;
		}
		try
		{
			if (resourceManagerSession == 0)
			{
				int num = viOpenDefaultRM(ref resourceManagerSession);
				DebugWrite("viOpenDefaultRM " + resourceManagerSession);
				if (num != 0)
				{
					resourceManagerSession = 0u;
					DebugWrite("viOpenDefaultRM() error: " + GetStatusCodeDescription(num));
					throw new Exception("viOpenDefaultRM() error: " + GetStatusCodeDescription(num));
				}
			}
		}
		catch (Exception ex2)
		{
			resourceManagerSession = 0u;
			ex2.Source = "Open " + ex2.Source;
			throw ex2;
		}
		try
		{
			DebugWrite("ViOpen " + resourceManagerSession);
			int num = viOpen(resourceManagerSession, resource, 0u, 0u, ref instrumentSession);
			DebugWrite("ViOpen returns " + resourceManagerSession + " InstrumentSession" + instrumentSession);
			if (num != 0)
			{
				DebugWrite("viOpen() error: " + GetStatusCodeDescription(num));
				throw new Exception("viOpen() error: " + GetStatusCodeDescription(num));
			}
		}
		catch (Exception ex3)
		{
			instrumentSession = 0u;
			ex3.Source = "Open " + ex3.Source;
			throw ex3;
		}
		try
		{
			int num = viSetAttribute(instrumentSession, 1073676312u, 10u);
			if (num < 0)
			{
				throw new Exception("viSetAttribute() error: " + GetStatusCodeDescription(num));
			}
			num = viSetAttribute(instrumentSession, 1073676344u, 1u);
			if (num != 0)
			{
				throw new Exception("viSetAttribute() error: " + GetStatusCodeDescription(num));
			}
			num = viSetAttribute(instrumentSession, 1073676314u, (uint)timeoutMilliseconds);
			if (num != 0)
			{
				throw new Exception("viSetAttribute() error: " + GetStatusCodeDescription(num));
			}
			num = viSetAttribute(instrumentSession, 1073676330u, 1u);
			if (num != 0)
			{
				throw new Exception("viSetAttribute() error: " + GetStatusCodeDescription(num));
			}
			num = viSetAttribute(instrumentSession, 1073676333u, 1u);
			if (num != 0)
			{
				throw new Exception("viSetAttribute() error: " + GetStatusCodeDescription(num));
			}
			num = viSetAttribute(instrumentSession, 1073676310u, 0u);
			if (num != 0)
			{
				throw new Exception("viSetAttribute() error: " + GetStatusCodeDescription(num));
			}
		}
		catch (Exception ex4)
		{
			ex4.Source = "Open " + ex4.Source;
			throw ex4;
		}
	}

	public void Dispose()
	{
		Close();
	}

	private string ReplaceCommonEscapeSequences(string str)
	{
		return str.Replace("\\n", "\n").Replace("\\r", "\r");
	}

	private string GetStatusCodeDescription(int statusCode)
	{
		try
		{
			byte[] array = new byte[256];
			viStatusDesc(instrumentSession, (uint)statusCode, array);
			return Encoding.ASCII.GetString(array).Replace("\0", "");
		}
		catch (Exception)
		{
			return "Unknown, status code: " + statusCode;
		}
	}
}
