using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Sample
{
    class LAN
    {
        // (0)クラス内変数
        private System.Net.Sockets.TcpClient LanSocket;                                 // LANソケット
        public string MsgBuf = "";                                                      // 受信データ

        // (1)接続
        public bool OpenInterface(string ipaddress, string port)
        {
            bool ret = false;
            System.Net.IPAddress ip = new System.Net.IPAddress(0);                      // IPアドレス

            try
            {
                if (System.Net.IPAddress.TryParse(ipaddress, out ip))
                {
                    LanSocket = new System.Net.Sockets.TcpClient();                     // LANソケットオブジェクトを作成
                    LanSocket.NoDelay = true;                                           // 送信の遅延(Nagleアルゴリズム)を無効にする
                    LanSocket.Connect(ip, Convert.ToInt32(port));                       // 接続
                    ret = true;
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }

            return ret;
        }

        // (2)切断
        public bool CloseInterface()
        {
            bool ret = false;

            try
            {
                LanSocket.Close();                                                      // LANソケットクローズ
                ret = true;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }

            return ret;
        }

        // (3)コマンド送信
        public bool SendMsg(string strMsg)
        {
            bool ret = false;
            byte[] SendBuffer = new byte[1024];

            try
            {
                strMsg += "\r\n";                                                       // ターミネータ「CR+LF」を付加
                SendBuffer = System.Text.Encoding.Default.GetBytes(strMsg);             // Convert to byte type
                LanSocket.GetStream().Write(SendBuffer, 0, SendBuffer.Length);          // 送信バッファに書き込み
                ret = true;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }

            return ret;
        }

        // (4)受信
        public bool ReceiveMsg(long timeout_ms)
        {
            bool ret = false;
            byte[] ary = new byte[65536];
            string rcv;
            int len;
            StringBuilder buf = new StringBuilder();
            Stopwatch sw = new Stopwatch();

            try
            {
                MsgBuf = "";                                                            // 受信データをクリア

                sw.Start();                                                             // タイムアウト用ストップウォッチを開始
                                                                                        // ターミネータ「LF」を受信するまでループ
                while (true)
                {
                    if (LanSocket.GetStream().DataAvailable == true)                    
                    {
                        len = LanSocket.GetStream().Read(ary, 0, ary.Length);           // 受信バッファから読み取り
                        rcv = Encoding.Default.GetString(ary).Substring(0, len);
                        rcv = rcv.Replace("\r", "");                                    // 受信データ内の「CR」を削除
                        if (rcv.IndexOf("\n") >= 0)                                     // ターミネータ「LF」を受信したら終了
                        {
                            rcv = rcv.Substring(0, rcv.IndexOf("\n"));                  // 受信データを「LF」の手前までで切り詰め
                            buf.Append(rcv);                                            // 受信データを保存
                            MsgBuf = buf.ToString();
                            break;
                        }
                        else
                        {
                            buf.Append(rcv);                                            // 受信データを保存
                        }
                    }
                    // タイムアウト処理
                    if (sw.ElapsedMilliseconds > timeout_ms)
                    {
                        MsgBuf = "Timeout";
                        MessageBox.Show(MsgBuf);
                        return ret;
                    }
                }
                sw.Stop();                                                              // ストップウォッチを停止
                ret = true;
            }
            catch (Exception e)
            {
                MsgBuf = "Error";
                MessageBox.Show(e.Message);
            }

            return ret;
        }

        // (5)コマンド送受信
        public bool SendQueryMsg(string strMsg, long timeout_ms)
        {
            bool ret = false;
            byte[] ary = new byte[65536];

            if (LanSocket.GetStream().DataAvailable == true)                            // 受信バッファにデータがあれば読み取り
            {
                LanSocket.GetStream().Read(ary, 0, ary.Length);
            }

            ret = SendMsg(strMsg);                                                      // コマンド送信
            if (ret)
            {
                if (strMsg.Contains("?"))
                {
                    ret = ReceiveMsg(timeout_ms);                                       // 送信が成功したら応答を受信
                }
            }

            return ret;
        }
    }

}
