using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Runtime.InteropServices;
using System.Data.SqlClient;
using System.Data;
using System.Data.OleDb;

namespace BEMSDataGateway
{
    public class IcosComm
    {
        //iCos 통신패킷 선언
        iCosMonitorValue _valuePacket;
        iCosMonitorText _textPacket;
        iCosLogInResponse _loginPacket;
        iCosMonitorValueArray _valueArrayPacket;
        iCosMonitorTextArray _textArrayPacket;
        iCosAlarmAckFromServer _alarmAckServerPacket;
        iCosAlarmNotify _alarmNotifyPacket;
        iCosAlarmAllAck _alarmAllAckPacket;
        LogFileCreate LFC = new LogFileCreate(); //로그 기록 파일
        //관제점정보 딕셔너리
        Dictionary<string, iCosTag> AddressData = new Dictionary<string, iCosTag>();
        Dictionary<int, iCosTagIndex> AddressIndex = new Dictionary<int, iCosTagIndex>();

        //통신연결정보 딕셔너리
        Dictionary<string, ClientData> Clients = new Dictionary<string, ClientData>();

        //통신 Critical section용 오브젝트
        private Object iCosCommObj = new Object();

        //통신응답 상위 전송용 딜리게이트 함수
        public delegate void iCosCallback(string userid, int nType, int nSubType, Object obj);
        public event iCosCallback iCosResponse;

        //통신 재접속용 쓰레드
        Thread ConnectionManageThread;
        Thread thread_connect;
        Thread thread_managerconnection;
        //통신 재접속용 쓰레드 초기화
        public void InitThread()
        {
            try
            {
                ConnectionManageThread = new Thread(new ThreadStart(ManagerConnection));
                ConnectionManageThread.IsBackground = true;
                ConnectionManageThread.Start();
                LFC.Log("=============================");

                if (Form1.Enable_EnglishMode)//영어
                {
                    LFC.Log("[IcosComm.cs] InitThread start");
                }
                else//한글
                {
                    LFC.Log("[IcosComm.cs] InitThread 시작");
                }
            }
            catch (ThreadStartException)
            {
                if (Form1.Enable_EnglishMode)//영어
                {
                    LFC.Log("[IcosComm.cs] InitThread down");
                }
                else//한글
                {
                    LFC.Log("[IcosComm.cs] InitThread 다운" + Environment.NewLine);
                }
            }
        }

        //관제점정보 DB에서 가져오기
        public bool InitTagAddress(int nDbType, string dbPath, string dbname, string dbid, string dbpassword) // MS-SQL 디폴트
        {
            bool bRet = false;
            string strSql = "SELECT * FROM TB_POINT";
            string strTag;
            int nDataCnt;
            string strCon;

            try
            {
                if (nDbType == 0) // MDB
                {
                    strCon = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + dbPath;
                    DataSet ds = new DataSet();
                    OleDbConnection mdbcon = null;
                    mdbcon = new OleDbConnection(strCon);
                    OleDbCommand mdbcmd = new OleDbCommand(strSql, mdbcon);
                    OleDbDataAdapter adp = new OleDbDataAdapter(mdbcmd);
                    mdbcon.Open();
                    adp.Fill(ds, "TB_POINT");

                    nDataCnt = ds.Tables[0].Rows.Count;

                    for (int i = 0; i < nDataCnt; i++)
                    {
                        iCosTag _tagAddr = new iCosTag();
                        iCosTagIndex _tagIndex = new iCosTagIndex();
                        _tagAddr.nChannel = Convert.ToInt32(ds.Tables[0].Rows[i][0]);
                        _tagAddr.nController = Convert.ToInt32(ds.Tables[0].Rows[i][1]);
                        _tagAddr.nDataType = Convert.ToInt32(ds.Tables[0].Rows[i][3]);
                        _tagAddr.nPoint = Convert.ToInt32(ds.Tables[0].Rows[i][2]);
                        _tagAddr.nState = 0;
                        _tagAddr.szText = "";
                        _tagAddr.analog = 0;
                        _tagAddr.digital = 0;
                        strTag = ds.Tables[0].Rows[i][4].ToString();
                        _tagIndex.szTag = strTag;
                        _tagIndex.nChannel = Convert.ToInt32(ds.Tables[0].Rows[i][0]);
                        _tagIndex.nController = Convert.ToInt32(ds.Tables[0].Rows[i][1]);
                        _tagIndex.nDataType = Convert.ToInt32(ds.Tables[0].Rows[i][3]);
                        _tagIndex.nPoint = Convert.ToInt32(ds.Tables[0].Rows[i][2]);

                        if (!String.IsNullOrEmpty(strTag))
                        {
                            if (AddressData.ContainsKey(strTag) == false)
                                AddressData.Add(strTag, _tagAddr);
                            bRet = true;
                        }
                        if (AddressIndex.ContainsKey(_tagAddr.nPoint) == false)
                        {
                            AddressIndex.Add(_tagIndex.nPoint, _tagIndex);
                        }
                    }
                    ds.Dispose();
                    mdbcon.Close();
                    mdbcon.Dispose();
                    mdbcmd.Dispose();
                    adp.Dispose();

                }
                else if (nDbType == 1)//MS-SQL
                {
                    strCon = @"Data Source = '" + dbPath + "'; Initial Catalog ='" + dbname + "';Persist Security Info=True; User ID = '" + dbid + "'; Password = '" + dbpassword + "'";
                    SqlConnection dbcon = new SqlConnection();
                    SqlCommand dbcmd = new SqlCommand();
                    dbcmd.CommandText = strSql;
                    dbcmd.Connection = dbcon;
                    dbcon.ConnectionString = strCon;
                    dbcon.Open();
                    SqlDataAdapter adp = new SqlDataAdapter(dbcmd);
                    DataSet ds = new DataSet();
                    adp.Fill(ds);

                    nDataCnt = ds.Tables[0].Rows.Count;

                    for (int i = 0; i < nDataCnt; i++)// channel, controller, point, datatype
                    {
                        iCosTag _tagAddr = new iCosTag();
                        iCosTagIndex _tagIndex = new iCosTagIndex();
                        _tagAddr.nChannel = Convert.ToInt32(ds.Tables[0].Rows[i][0]);
                        _tagAddr.nController = Convert.ToInt32(ds.Tables[0].Rows[i][1]);
                        _tagAddr.nDataType = Convert.ToInt32(ds.Tables[0].Rows[i][3]);
                        _tagAddr.nPoint = Convert.ToInt32(ds.Tables[0].Rows[i][2]);
                        _tagAddr.nState = 0;
                        _tagAddr.szText = "";
                        _tagAddr.analog = 0;
                        _tagAddr.digital = 0;
                        strTag = ds.Tables[0].Rows[i][4].ToString();
                        _tagIndex.szTag = strTag;
                        _tagIndex.nChannel = Convert.ToInt32(ds.Tables[0].Rows[i][0]);
                        _tagIndex.nController = Convert.ToInt32(ds.Tables[0].Rows[i][1]);
                        _tagIndex.nDataType = Convert.ToInt32(ds.Tables[0].Rows[i][3]);
                        _tagIndex.nPoint = Convert.ToInt32(ds.Tables[0].Rows[i][2]);

                        if (!String.IsNullOrEmpty(strTag))
                        {
                            if (AddressData.ContainsKey(strTag) == false)
                                AddressData.Add(strTag, _tagAddr);
                            bRet = true;
                        }
                        if (AddressIndex.ContainsKey(_tagAddr.nPoint) == false)
                        {
                            AddressIndex.Add(_tagIndex.nPoint, _tagIndex);
                        }
                    }
                    dbcon.Close();
                    dbcon.Dispose();
                    dbcmd.Dispose();
                    adp.Dispose();
                    ds.Dispose();
                }
            }
            catch
            {
                bRet = false;
            }
            return bRet;
        }

        //iCos통신 수신 확인 함수
        public void RecvThread(Object target)
        {
            ClientData client = (ClientData)target;

            byte[] buffer = new byte[8192];
            byte[] buffer2 = new byte[8192];
            byte[] blength = new byte[4];
            byte[] bPacketType = new byte[4];
            byte[] bPacketSubType = new byte[4];

            int nlength = 0;
            int nPacketType = 0;
            int nPacketSubType = 0;
            string strTag;

            while (client.clientSocket.Connected)
            {
                lock (iCosCommObj)
                {
                    try
                    {
                        try
                        {
                            client.readStream.Read(blength, 0, 4);
                        }
                        catch (Exception e)
                        {
                            if (Form1.Enable_EnglishMode)//영어
                            {
                                LFC.Log("[IcosComm.cs] client.readStream.Read fail : " + e + ", " + Environment.NewLine);
                            }
                            else//한글
                            {
                                LFC.Log("[IcosComm.cs] client.readStream.Read 실패 : " + e + ", " + Environment.NewLine);
                            }
                            break;
                        }
                        nlength = BitConverter.ToInt32(blength, 0);
                        if ((nlength > 0) && (nlength < 8192))
                        {
                            client.readStream.Read(buffer2, 0, nlength - 4);
                            Array.Copy(blength, 0, buffer, 0, 4);       //blength 0부터 4개를 buffer 0부터 복사
                            Array.Copy(buffer2, 0, buffer, 4, nlength); //buffer2 0부터 nlength개를 buffer 4부터 복사
                            Array.Copy(buffer, 4, bPacketType, 0, 4);   //buffer 4부터 4개를 bPacketType 0부터 복사
                            Array.Copy(buffer, 8, bPacketSubType, 0, 4);//buffer 8부터 4개를 bPacketSubType 0부터 복사
                            nPacketType = BitConverter.ToInt32(bPacketType, 0);
                            nPacketSubType = BitConverter.ToInt32(bPacketSubType, 0);
                        }                                               //buffer 0~4 길이, buffer 4~8  PacketType, buffer 8~12 PacketSubType
                        else
                            continue;

                        if (nPacketType == 3)
                        {
                            if (nPacketSubType == 4)
                            {
                                if ((buffer[20] >= 0) && (buffer[20] <= 5))
                                {
                                    _valuePacket.Deserialize(buffer);
                                    strTag = AddressIndex[_valuePacket.nPoint].szTag;
                                    AddressData[strTag].nState = _valuePacket.nState;
                                    AddressData[strTag].analog = _valuePacket.Values.analog;
                                    AddressData[strTag].digital = _valuePacket.Values.digital;
                                }
                                else if (buffer[20] == 6)
                                {
                                    _textPacket.Deserialize(buffer);
                                    strTag = AddressIndex[_textPacket.nPoint].szTag;
                                    AddressData[strTag].nState = _textPacket.nState;
                                    AddressData[strTag].szText = _textPacket.szTextValue;
                                }
                            }
                            else if (nPacketSubType == 22)
                            {
                                _valueArrayPacket.Values = new PointValue[50];
                                _valueArrayPacket.Deserialize(buffer);
                                for (int i = 0; i < _valueArrayPacket.nPntCnt; i++)
                                {
                                    strTag = AddressIndex[_valueArrayPacket.Values[i].nPoint].szTag;
                                    AddressData[strTag].nState = _valueArrayPacket.Values[i].nState;
                                    AddressData[strTag].analog = _valueArrayPacket.Values[i].Values.analog;
                                    AddressData[strTag].digital = _valueArrayPacket.Values[i].Values.digital;
                                }
                            }
                            else if (nPacketSubType == 23)
                            {
                                _textArrayPacket.Values = new PointText[5];
                                _textArrayPacket.Deserialize(buffer);
                                for (int i = 0; i < _textArrayPacket.nPntCnt; i++)
                                {
                                    strTag = AddressIndex[_textArrayPacket.Values[i].nPoint].szTag;
                                    AddressData[strTag].nState = _textArrayPacket.Values[i].nState;
                                    AddressData[strTag].szText = _textArrayPacket.Values[i].szTextValue;
                                }
                            }
                            else
                            {
                                int fail = buffer[8];
                            }
                        }
                        else if (nPacketType == 6)
                        {
                            if (nPacketSubType == 2)
                            {
                                _loginPacket.Deserialize(buffer);
                                iCosResponse(client.icosId, nPacketType, nPacketSubType, _loginPacket);
                            }
                        }
                        else if (nPacketType == 4) //PTYPE_ALARM
                        {
                            if (nPacketSubType == 11) //ALARM_NOTIFY
                            {
                                _alarmNotifyPacket.Deserialize(buffer);
                                iCosResponse(client.icosId, nPacketType, nPacketSubType, _alarmNotifyPacket);
                            }
                            else if (nPacketSubType == 9) //ALARM_ACK_FROM_SERVER
                            {
                                _alarmAckServerPacket.Deserialize(buffer);
                                iCosResponse(client.icosId, nPacketType, nPacketSubType, _alarmAckServerPacket);
                            }
                            else if (nPacketSubType == 16) //ALARM_CHACK_ALL_PROCESS_FROM_SERVER
                            {
                                _alarmAllAckPacket.Deserialize(buffer);
                                iCosResponse(client.icosId, nPacketType, nPacketSubType, _alarmAllAckPacket);
                            }
                            else
                            {
                                iCosResponse(client.icosId, nPacketType, nPacketSubType, null);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        if (Form1.Enable_EnglishMode)//영어
                        {
                            LFC.Log("[IcosComm.cs] Icos Communication failure : " + e + ", " + Environment.NewLine);
                        }
                        else//한글
                        {
                            LFC.Log("[IcosComm.cs] Icos 통신실패 : " + e + ", " + Environment.NewLine);
                        }
                    }
                }
            }
            if (Form1.Enable_EnglishMode)//영어
            {
                LFC.Log("[IcosComm.cs] Icos Terminate control point thread" + Environment.NewLine);
            }
            else//한글
            {
                LFC.Log("[IcosComm.cs] Icos 관제점 쓰레드 종료" + Environment.NewLine);
            }
        }

        public void ManagerConnection()
        {
            while (true)
            {
                System.Threading.Thread.Sleep(10000);

                lock (iCosCommObj)
                {
                    if (Clients.Count < 1)
                        continue;

                    foreach (KeyValuePair<string, ClientData> client in Clients)
                    {
                        if (client.Value.clientSocket.Connected == false)
                        {
                            string icosAddr = client.Value.ipAddress;
                            int icosPort = client.Value.nPort;
                            string icosId = client.Value.icosId;
                            string icosPassword = client.Value.icosPassword;

                            Socket newclient = null;
                            IPEndPoint icosCon = new IPEndPoint(IPAddress.Parse(icosAddr), icosPort);
                            newclient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);

                            try
                            {
                                newclient.Connect(icosCon);
                                NetworkStream readStream = new NetworkStream(newclient);

                                Clients[icosId].clientSocket = newclient;
                                Clients[icosId].readStream = readStream;
                                ClientData _conData = new ClientData();
                                _conData.clientSocket = newclient;
                                _conData.readStream = readStream;
                                _conData.ipAddress = icosAddr;
                                _conData.nPort = icosPort;
                                _conData.icosId = icosId;
                                _conData.icosPassword = icosPassword;

                                thread_managerconnection = new Thread(new ParameterizedThreadStart(RecvThread));
                                thread_managerconnection.IsBackground = true;
                                thread_managerconnection.Start(_conData);

                                IcosLogin(icosId, icosPassword);
                                System.Threading.Thread.Sleep(1000);
                                if (Form1.Enable_EnglishMode)//영어
                                {
                                    LFC.Log("[IcosComm.cs] ManagerConnection reconnect succeeded" + Environment.NewLine);
                                }
                                else//한글
                                {
                                    LFC.Log("[IcosComm.cs] ManagerConnection 재접속 성공" + Environment.NewLine);
                                }
                            }
                            catch
                            {
                                newclient.Close();
                                newclient.Dispose();
                                if (Form1.Enable_EnglishMode)//영어
                                {
                                    LFC.Log("[IcosComm.cs] ManagerConnection reconnect failed" + Environment.NewLine);
                                }
                                else//한글
                                {
                                    LFC.Log("[IcosComm.cs] ManagerConnection 재접속 실패" + Environment.NewLine);
                                }
                            }
                        }
                    }
                }
            }
        }
        //iCos 통신 접속 함수
        public bool Connect(string icosAddr, int icosPort, string icosId, string icosPassword)
        {
            bool bRet = false;

            lock (iCosCommObj)
            {
                Socket client = null;
                IPEndPoint icosCon = new IPEndPoint(IPAddress.Parse(icosAddr), icosPort);
                client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);

                try
                {
                    if ((!String.IsNullOrEmpty(icosId)) && (Clients.ContainsKey(icosId) == false))
                    {
                        client.Connect(icosCon);
                        NetworkStream readStream = new NetworkStream(client);
                        ClientData _conData = new ClientData();
                        _conData.clientSocket = client;
                        _conData.readStream = readStream;
                        _conData.ipAddress = icosAddr;
                        _conData.nPort = icosPort;
                        _conData.icosId = icosId;
                        _conData.icosPassword = icosPassword;
                        Clients.Add(icosId, _conData);

                        thread_connect = new Thread(new ParameterizedThreadStart(RecvThread));
                        thread_connect.IsBackground = true;
                        thread_connect.Start(_conData);

                        bRet = true;
                    }
                    else
                    {
                        return bRet;
                    }
                }
                catch
                {
                    if (Form1.Enable_EnglishMode)//영어
                    {
                        LFC.Log("[IcosComm.cs] Icos Connect Failed" + Environment.NewLine);
                    }
                    else//한글
                    {
                        LFC.Log("[IcosComm.cs] Icos Connect 실패" + Environment.NewLine);
                    }
                    client.Close();
                    client.Dispose();
                    return bRet;
                }
            }
            return bRet;
        }

        //iCos 통신 끊기 함수
        public void Disconnect(string icosId)
        {
            if ((String.IsNullOrEmpty(icosId)) || (Clients.ContainsKey(icosId) == false))
                return;

            lock (iCosCommObj)
            {
                Clients[icosId].clientSocket.Close();
                Clients.Remove(icosId);
            }
        }
        public void reDisconnect(string icosId)
        {
            iCosCommObj = new Object();
            if ((String.IsNullOrEmpty(icosId)) || (Clients.ContainsKey(icosId) == false))
                return;
            IcosLogout(icosId);
            lock (iCosCommObj)
            {
                Clients[icosId].clientSocket.Close();
                Clients.Remove(icosId);
            }
        }
        //iCos 로그인 함수
        public void IcosLogin(string userid, string password)
        {
            if ((String.IsNullOrEmpty(userid)) && (Clients.ContainsKey(userid) == false))
                return;

            iCosLogInRequest PacketData = new iCosLogInRequest();
            if (Clients[userid].clientSocket.Connected == true)
            {
                PacketData.nLength = Marshal.SizeOf(PacketData);
                PacketData.nType = 6;
                PacketData.nSubType = 1;
                PacketData.szId = userid;
                PacketData.szPassword = password;
                Clients[userid].icosId = userid;
                Clients[userid].icosPassword = password;

                NetworkStream writeStream = new NetworkStream(Clients[userid].clientSocket);
                writeStream.Write(PacketData.Serialize(), 0, Marshal.SizeOf(PacketData));
                writeStream.Close();
                writeStream.Dispose();
            }
        }

        //iCos 로그아웃 함수
        public void IcosLogout(string userid)
        {
            if ((String.IsNullOrEmpty(userid)) || (Clients.ContainsKey(userid) == false))
                return;

            iCosLogInRequest PacketData = new iCosLogInRequest();
            if (Clients[userid].clientSocket.Connected == true)
            {
                PacketData.nLength = Marshal.SizeOf(PacketData);
                PacketData.nType = 6;
                PacketData.nSubType = 3;
                PacketData.szId = userid;
                PacketData.szPassword = "";

                NetworkStream writeStream = new NetworkStream(Clients[userid].clientSocket);
                writeStream.Write(PacketData.Serialize(), 0, Marshal.SizeOf(PacketData));
                writeStream.Close();
                writeStream.Dispose();
            }
        }

        //iCos 관제점 등록 함수
        public int IcosRegTag(string userid, int nCnt, string tags)
        {
            if ((String.IsNullOrEmpty(userid)) && (Clients.ContainsKey(userid) == false))
                return 0;

            if (nCnt < 1)
                return 0;

            string[] icosTag = tags.Split(',');
            foreach (string tag in icosTag)
            {
                if (!AddressData.ContainsKey(tag))
                    continue;

                iCosMonitorRegTag PacketData = new iCosMonitorRegTag();
                if (Clients[userid].clientSocket.Connected == true)
                {
                    PacketData.nLength = Marshal.SizeOf(PacketData);
                    PacketData.nType = 3;
                    PacketData.nSubType = 2;
                    PacketData.nChannel = AddressData[tag].nChannel;
                    PacketData.nController = AddressData[tag].nController;
                    PacketData.nDataType = AddressData[tag].nDataType;
                    PacketData.nPoint = AddressData[tag].nPoint;

                    if (Clients[userid].RegTag.Contains(tag) == false)
                        Clients[userid].RegTag.Add(tag);
                    NetworkStream writeStream = new NetworkStream(Clients[userid].clientSocket);
                    writeStream.Write(PacketData.Serialize(), 0, Marshal.SizeOf(PacketData));
                    writeStream.Close();
                    writeStream.Dispose();
                }
            }
            return 1;
        }

        //iCos 관제점 등록삭제 함수
        public int IcosUnregTag(string userid, int nCnt, string tags)
        {
            if ((String.IsNullOrEmpty(userid)) && (Clients.ContainsKey(userid) == false))
                return 0;

            if (nCnt < 1)
                return 0;

            string[] icosTag = tags.Split(',');
            foreach (string tag in icosTag)
            {
                if (!AddressData.ContainsKey(tag))
                    continue;

                iCosMonitorRegTag PacketData = new iCosMonitorRegTag();
                if (Clients[userid].clientSocket.Connected == true)
                {
                    PacketData.nLength = Marshal.SizeOf(PacketData);
                    PacketData.nType = 3;
                    PacketData.nSubType = 3;
                    PacketData.nChannel = AddressData[tag].nChannel;
                    PacketData.nController = AddressData[tag].nController;
                    PacketData.nDataType = AddressData[tag].nDataType;
                    PacketData.nPoint = AddressData[tag].nPoint;

                    if (Clients[userid].RegTag.Contains(tag) == true)
                        Clients[userid].RegTag.Remove(tag);
                    NetworkStream writeStream = new NetworkStream(Clients[userid].clientSocket);
                    writeStream.Write(PacketData.Serialize(), 0, Marshal.SizeOf(PacketData));
                    writeStream.Close();
                    writeStream.Dispose();
                }
            }
            return 1;
        }

        //iCos 관제점 값제어 함수, 쓰기
        public void IcosControlValue(string userid, string tag, float fvalue)
        {
            if ((String.IsNullOrEmpty(userid)) && (Clients.ContainsKey(userid) == false))
                return;

            if (!AddressData.ContainsKey(tag))
                return;

            iCosMonitorValue PacketData = new iCosMonitorValue();
            if (Clients[userid].clientSocket.Connected == true)
            {
                NetworkStream writeStream = new NetworkStream(Clients[userid].clientSocket);

                PacketData.nLength = Marshal.SizeOf(PacketData);
                PacketData.nType = 3;
                PacketData.nSubType = 5;
                PacketData.nChannel = AddressData[tag].nChannel;
                PacketData.nController = AddressData[tag].nController;
                PacketData.nDataType = AddressData[tag].nDataType;
                PacketData.nPoint = AddressData[tag].nPoint;
                PacketData.nState = 1;
                PacketData.nReserved1 = 0;
                PacketData.nReserved2 = 0;
                if (PacketData.nDataType < 2)
                    PacketData.Values.analog = fvalue;
                else
                    PacketData.Values.digital = (byte)fvalue;

                writeStream.Write(PacketData.Serialize(), 0, Marshal.SizeOf(PacketData));
                writeStream.Close();
                writeStream.Dispose();
            }
        }

        //iCos 관제점 문자열제어 함수
        public void IcosControlText(string userid, string tag, string txtvalue)
        {
            if ((String.IsNullOrEmpty(userid)) && (Clients.ContainsKey(userid) == false))
                return;

            if (!AddressData.ContainsKey(tag))
                return;

            iCosMonitorText PacketData = new iCosMonitorText();
            if (Clients[userid].clientSocket.Connected == true)
            {
                NetworkStream writeStream = new NetworkStream(Clients[userid].clientSocket);

                PacketData.nLength = Marshal.SizeOf(PacketData);
                PacketData.nType = 3;
                PacketData.nSubType = 5;
                PacketData.nChannel = AddressData[tag].nChannel;
                PacketData.nController = AddressData[tag].nController;
                PacketData.nDataType = AddressData[tag].nDataType;
                PacketData.nPoint = AddressData[tag].nPoint;
                PacketData.nState = 1;
                PacketData.nReserved1 = 0;
                PacketData.nReserved2 = 0;
                PacketData.szTextValue = txtvalue;

                writeStream.Write(PacketData.Serialize(), 0, Marshal.SizeOf(PacketData));
                writeStream.Close();
                writeStream.Dispose();
            }
        }

        //관제점
        public void IcosRegTagArray(string userid, int nCnt, string tags)
        {
            if ((String.IsNullOrEmpty(userid)) && (Clients.ContainsKey(userid) == false))
                return;

            if (nCnt < 1)
                return;

            if (Clients[userid].clientSocket.Connected == false)
                return;

            iCosMonitorRegTagArray PacketData = new iCosMonitorRegTagArray();
            PacketData.Tags = new TagAddr[50];
            NetworkStream writeStream = new NetworkStream(Clients[userid].clientSocket);
            string[] icosTag = tags.Split(',');
            int nIndex = 0;
            int nSendCnt = 0;

            foreach (string tag in icosTag)
            {
                if (!AddressData.ContainsKey(tag))
                {
                    nSendCnt++;
                    continue;
                }

                PacketData.nLength = Marshal.SizeOf(PacketData);
                PacketData.nType = 3;
                PacketData.nSubType = 26;
                PacketData.nPntCnt = nIndex + 1;
                PacketData.Tags[nIndex].nChannel = AddressData[tag].nChannel;
                PacketData.Tags[nIndex].nController = AddressData[tag].nController;
                PacketData.Tags[nIndex].nDataType = AddressData[tag].nDataType;
                PacketData.Tags[nIndex].nPoint = AddressData[tag].nPoint;
                nSendCnt++;
                nIndex++;

                if (Clients[userid].RegTag.Contains(tag) == false)
                    Clients[userid].RegTag.Add(tag);
                if ((nIndex >= 50) || (nIndex >= nCnt) || (nSendCnt >= nCnt))
                {
                    writeStream.Write(PacketData.Serialize(), 0, Marshal.SizeOf(PacketData));
                    nIndex = 0;
                    PacketData.nPntCnt = 0;
                }
            }
        }

        public void IcosUnregTagArray(string userid, int nCnt, string tags)
        {
            if ((String.IsNullOrEmpty(userid)) && (Clients.ContainsKey(userid) == false))
                return;

            if (nCnt < 1)
                return;

            if (Clients[userid].clientSocket.Connected == false)
                return;

            iCosMonitorRegTagArray PacketData = new iCosMonitorRegTagArray();
            PacketData.Tags = new TagAddr[50];
            NetworkStream writeStream = new NetworkStream(Clients[userid].clientSocket);
            string[] icosTag = tags.Split(',');
            int nIndex = 0;
            int nSendCnt = 0;

            foreach (string tag in icosTag)
            {
                if (!AddressData.ContainsKey(tag))
                {
                    nSendCnt++;
                    continue;
                }

                PacketData.nLength = Marshal.SizeOf(PacketData);
                PacketData.nType = 3;
                PacketData.nSubType = 27;
                PacketData.nPntCnt = nIndex + 1;
                PacketData.Tags[nIndex].nChannel = AddressData[tag].nChannel;
                PacketData.Tags[nIndex].nController = AddressData[tag].nController;
                PacketData.Tags[nIndex].nDataType = AddressData[tag].nDataType;
                PacketData.Tags[nIndex].nPoint = AddressData[tag].nPoint;
                nSendCnt++;
                nIndex++;

                if (Clients[userid].RegTag.Contains(tag) == true)
                    Clients[userid].RegTag.Remove(tag);
                if ((nIndex >= 50) || (nIndex >= nCnt) || (nSendCnt >= nCnt))
                {
                    writeStream.Write(PacketData.Serialize(), 0, Marshal.SizeOf(PacketData));
                    nIndex = 0;
                    PacketData.nPntCnt = 0;
                }
            }
        }

        public string IcosGetTagText(string strTag)
        {
            string szRet = "";

            if ((String.IsNullOrEmpty(strTag)) || (AddressData.ContainsKey(strTag) == false))
                return szRet;

            szRet = AddressData[strTag].szText;

            return szRet;
        }

        //읽기
        public double IcosGetTagValue(string strTag)
        {
            double fRet = 0;

            if ((String.IsNullOrEmpty(strTag)) || (AddressData.ContainsKey(strTag) == false))
                return fRet;

            if (AddressData[strTag].nDataType < 2)
                fRet = AddressData[strTag].analog;
            else if ((AddressData[strTag].nDataType > 1) && (AddressData[strTag].nDataType < 6))
                fRet = AddressData[strTag].digital;

            return fRet;
        }

        public string GetTagNameByIndex(int nPnt)
        {
            string szRet = "";

            if (AddressIndex.ContainsKey(nPnt) == true)
            {
                szRet = AddressIndex[nPnt].szTag;
            }
            return szRet;
        }

        public int GetRegTagCount(string userid)
        {
            int nRet = 0;
            if ((String.IsNullOrEmpty(userid)) || (Clients.ContainsKey(userid) == false))
                return nRet;

            nRet = Clients[userid].RegTag.Count;

            return nRet;
        }

        public string GetRegTags(string userid)
        {
            string szReg = "";
            if ((String.IsNullOrEmpty(userid)) || (Clients.ContainsKey(userid) == false))
                return szReg;

            for (int i = 0; i < Clients[userid].RegTag.Count; i++)
            {
                szReg = szReg + Clients[userid].RegTag[i];
                if (i < Clients[userid].RegTag.Count - 1)
                    szReg = szReg + ",";
            }
            return szReg;
        }

        public bool GetConnectionStatus(string userid)
        {
            if ((String.IsNullOrEmpty(userid)) || (Clients.ContainsKey(userid) == false))
                return false;

            bool bRet = Clients[userid].clientSocket.Connected;
            return bRet;
        }

        public bool GetTagAddress(string strTag, ref int nChannel, ref int nController, ref int nType, ref int nPoint, ref int nState)
        {
            if ((String.IsNullOrEmpty(strTag)) || (AddressData.ContainsKey(strTag) == false))
                return false;

            nChannel = AddressData[strTag].nChannel;
            nController = AddressData[strTag].nController;
            nType = AddressData[strTag].nDataType;
            nPoint = AddressData[strTag].nPoint;
            nState = AddressData[strTag].nState;
            return true;
        }
    }
}