using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Diagnostics;

namespace CommLib
{
    /// <summary>
    /// Třída pro jednoduchou (blokující) Tcp komunikaci na principu dotaz/odpověď
    /// </summary>
    public class TcpClientComm : IDisposable
    {
        TcpClient tcpClient;
        byte[] tcpBuffer = new byte[1024];

        public IPEndPoint EndPoint { get; private set; }
        int timeout;

        /// <summary>
        /// Vytvoření instance s navázáním spojení na cílovou adresu a port
        /// </summary>
        /// <param name="ip">IP adresa cíle</param>
        /// <param name="port">TCP port cíle</param>
        /// <param name="timeout">Timeout v ms</param>
        public TcpClientComm(IPAddress ip, UInt16 port, int timeout)
        {
            EndPoint = new IPEndPoint(ip, port);
            this.timeout = timeout;

            tcpClient = new TcpClient();
            tcpClient.Client.ReceiveTimeout = timeout;
            tcpClient.Client.SendTimeout = timeout;

            tcpClient.Connect(EndPoint);
        }

        /// <summary>
        /// Odeslání zprávy bez čekání na odpověď
        /// </summary>
        /// <param name="message"></param>
        public void Send(string message)
        {
            byte[] b = Encoding.ASCII.GetBytes(message);
            tcpClient.Client.Send(b);
        }

        /// <summary>
        /// Odeslání zprávy s čekáním na odpověď
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public string SendReceive(string message)
        {
            int c;
            try
            {
                Send(message);
                c = tcpClient.Client.Receive(tcpBuffer);
            }
            catch
            {
                // v případě neúspěchu znovunavázání spojení
                tcpClient.Close();
                tcpClient = new TcpClient();
                tcpClient.Client.ReceiveTimeout = timeout;
                tcpClient.Client.SendTimeout = timeout;
                tcpClient.Connect(EndPoint);

                Send(message);
                c = tcpClient.Client.Receive(tcpBuffer);
            }
            return Encoding.Default.GetString(tcpBuffer, 0, c);
        }

        /// <summary>
        /// Uzavření spojení
        /// </summary>
        public void Close()
        {
            tcpClient.Close();
        }

        #region dispose

        private bool IsDisposed;

        public virtual void Dispose()
        {
            if (!this.IsDisposed)
            {
                tcpClient.Close();
                this.IsDisposed = true;
            }
        }
        #endregion
    }
}
