using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Demo_CSharp
{
    public class VisaInstrument
    {
        private int m_nResourceManager;
        private int m_nSession;

        public VisaInstrument()
        {
            OpenResourceManager();
        }
        ~VisaInstrument()
        {
            Close();
        }

        private void Close()
        {
            if (m_nSession != 0)
                visa32.viClose(m_nSession);
            if (m_nResourceManager != 0)
                visa32.viClose(m_nResourceManager);
        }

        public bool WriteBytes(byte[] DataArray)
        {
            int state = visa32.viWrite(m_nSession, DataArray, DataArray.Length, out var nBytesWritten);
            return state == visa32.VI_SUCCESS;
        }

        public bool WriteBytes(string str)
        {
            var dataArray = Encoding.Default.GetBytes(str);
            int state = visa32.viWrite(m_nSession, dataArray, dataArray.Length, out var nBytesWritten);
            return state == visa32.VI_SUCCESS;
        }

        public string ReadBytes()
        {
            List<byte[]> byteList = new List<byte[]>();
            int readValue = -1;
            bool readResult = false;
            do
            {
                int maxcount = 1024;    
                int retCount = 0;       
                byte[] buff = new byte[maxcount];
                readValue = visa32.viRead(m_nSession, buff, maxcount, out retCount);
                if (retCount > 0)
                {
                    byte[] invalidBuff = new byte[retCount];
                    Array.Copy(buff, 0, invalidBuff, 0, retCount);
                    byteList.Add(invalidBuff);
                }
                if (readValue == visa32.VI_SUCCESS || readValue== visa32.VI_SUCCESS_TERM_CHAR)
                {
                    readResult = true;
                    break;
                }
            }
            while (readValue == visa32.VI_SUCCESS_MAX_CNT);

            if (readResult == false)
            {
                return "read error";
            }
            if (byteList.Count > 0)
            {
                List<int> allCount = byteList.Select(o => o.Length).ToList();
                var count = allCount.Sum();
                var allBytes = new byte[count];
                int index = 0;
                for (int i = 0; i < byteList.Count; i++)
                {
                    var byteArray = byteList[i];
                    byteArray.CopyTo(allBytes, index);
                    index += byteArray.Length;
                }
                var stringValue = Encoding.Default.GetString(allBytes);
                return stringValue;
            }
            return string.Empty;
        }

        private bool OpenResourceManager()
        {
            int nViStatus = visa32.viOpenDefaultRM(out this.m_nResourceManager);
            return nViStatus == visa32.VI_SUCCESS;
        }

        public bool OpenSession(string deviceAddress)
        {
            int nViStatus = visa32.viOpen(this.m_nResourceManager, deviceAddress, visa32.VI_NO_LOCK,
                visa32.VI_TMO_IMMEDIATE, out this.m_nSession);
            return nViStatus == visa32.VI_SUCCESS;
        }

        public List<string> FindDevices()
        {
            var exprList = new List<string>() { "?*INSTR", "?*SOCKET" };
            var deviceList = new HashSet<string>();
            foreach (var expr in exprList)
            {
                int vi, retCount;
                var sb = new StringBuilder();
                visa32.viFindRsrc(m_nResourceManager, expr, out vi, out retCount, sb);
                if (retCount > 0)
                {
                    if (sb.Length > 0)
                        deviceList.Add(sb.ToString());
                    for (int i = 0; i < retCount; i++)
                    {
                        var sbb = new StringBuilder(50);
                        visa32.viFindNext(vi, sbb);
                        deviceList.Add(sbb.ToString());
                    }
                }

            }
            return deviceList.ToList();
        }


        /// <summary>
        /// 设置SOCKET通信时结束符
        /// socket通信时，如果不设置，会一直提示超时
        /// </summary>
        public bool SetATTR_TERMCHAR_EN()
        {
            int nViStatus = visa32.viSetAttribute(m_nSession, visa32.VI_ATTR_TERMCHAR_EN, 1);
            return nViStatus == visa32.VI_SUCCESS;
        }

        /// <summary>
        /// 获取通信端口类型 socket | instr
        /// </summary>
        /// <returns></returns>
        public string GetAttributeType()
        {
            StringBuilder sb = new StringBuilder(100);
            var state = visa32.viGetAttribute(m_nSession, visa32.VI_ATTR_RSRC_CLASS, sb);
            if (state == visa32.VI_SUCCESS)
            {
                return sb.ToString().ToUpper();
            }
            return string.Empty;
        }
    }


}
