using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace Zone_Fix.Networking
{
    class HandleClient
    {
        public Boolean IsConnected = true;

        private String Name;
        private Int32 ConnectPort;

        private IPEndPoint ClientEndPoint;
        private Socket ClientSocket;
        private Byte[] ClientBuffer;

        private HandleServer ServerSocket;

        public HandleClient(String HandleName, Int32 HandleConnectPort, Socket HandleSocket)
        {
            Name = HandleName;
            ConnectPort = HandleConnectPort;

            ClientSocket = HandleSocket;
            ClientEndPoint = (IPEndPoint)HandleSocket.RemoteEndPoint;

            ServerSocket = new HandleServer(Name, ConnectPort, ClientEndPoint, this);

            Program.Writer.WriteBlank(true, "({0}) Has Connected -> {1}, Remote Port -> {2}", ClientEndPoint.Address, Name, ClientEndPoint.Port);

            Receive();
        }

        private void Receive()
        {
            try
            {
                ClientBuffer = new Byte[Program.Byte_Size];

                ClientSocket.BeginReceive(ClientBuffer, 0, ClientBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), ClientSocket);
            }
            catch (Exception Error) { DisconnectWithException(Error.Message); }
        }

        private void ReceiveMessage(IAsyncResult Result)
        {
            try
            {
                Int32 ReceiveLength = ClientSocket.EndReceive(Result);

                Array.Resize(ref ClientBuffer, ReceiveLength);

                if (ReceiveLength != 0 && ServerSocket.IsConnected && Program.Analyse.CheckClient(Program.BytesToHex(ClientBuffer), ReceiveLength))
                {
                    ServerSocket.Send(ClientBuffer, ReceiveLength);

                    Receive();
                }
                else
                {
                    IsConnected = false;

                    Program.Writer.WriteBlank(true, "({0}) Has Disconnected -> {1}", ClientEndPoint.Address, Name);

                    Close();

                    return;
                }
            }
            catch (Exception Error) { DisconnectWithException(Error.Message); }
        }

        public void Close()
        {
            try
            {
                ClientSocket.Disconnect(false);
                ClientSocket.Close();

                if (ClientSocket != null) { ClientSocket.Dispose(); }
            }
            catch { }
        }

        private void DisconnectWithException(String Exception)
        {
            IsConnected = false;

            //Program.Writer.WriteBlank(true, "({0}) Has Disconnected -> {1}, Exception -> {2}", ClientEndPoint.Address, Name, Exception);

            Close();

            return;
        }

        public void Send(Byte[] Buffer, Int32 Length)
        {
            try
            {
                //Program.Writer.WriteBlank(true, "({0}) Sent Message -> {1}, Length -> {2}", Name, ClientEndPoint.Address, Length);

                ClientSocket.Send(Buffer);
            }
            catch (Exception Error) { DisconnectWithException(Error.Message); }
        }
    }
}
