using System.Net;
using System.Net.Sockets;
using System.Text;
using GatewaySCO;

namespace gatewayPruebaECO;

// Cliente de pruebas del gateway, remite mensajes, espera respuesta.
// public class SocketClientECO
// {
//     private const int Port = 6697; // Puerto del servidor gateway
//     private const string Server = "127.0.0.1"; // Dirección IP del servidor

//     // Crear un socket
//     static Socket socket = new(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//     static int numeroRespuestas = 0;

//     public static void Main()
//     {
//         try
//         {
//             // Conectarse al servidor
//             socket.Connect(new IPEndPoint(IPAddress.Parse(Server), Port));
//             Console.WriteLine("Conectado al servidor.");
//             var tareaRemiteRespuesta = Task.Run(() => EsperarMensajesAsync());

//             string mensaje1 = """
//             soeps~Message-Type=REQ|Session-Id=400|~<?xml version="1.0" encoding="UTF-8"?><scsns:Initialize xmlns:scsns="http://bc.si.retail.ibm.com/POSBCSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://bc.si.retail.ibm.com/POSBCSchema C:\PosBc\POSBCSchema_main.xsd">
//             <InitializeRequest>
//                 <OperatorID>NO_DEFAULT</OperatorID>
//                 <TerminalNumber>400</TerminalNumber>
//                 <Recovery>false</Recovery>
//             </InitializeRequest>
//             </scsns:Initialize>
//             """;

//             Mensaje(mensaje1);

//             string mensaje2 = """
//             soeps~Message-Type=REQ|Session-Id=400|~<?xml version="1.0" encoding="UTF-8"?><scsns:Initialize xmlns:scsns="http://bc.si.retail.ibm.com/POSBCSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://bc.si.retail.ibm.com/POSBCSchema C:\PosBc\POSBCSchema_main.xsd">
//             <InitializeRequest>
//                 <OperatorID>NO_DEFAULT</OperatorID>
//                 <TerminalNumber>800</TerminalNumber>
//                 <Recovery>false</Recovery>
//             </InitializeRequest>
//             </scsns:Initialize>
//             """;

//             Mensaje(mensaje2);

//             string mensaje3 = """
//             soeps~Message-Type=REQ|Session-Id=400|~<?xml version="1.0" encoding="UTF-8"?><scsns:Initialize xmlns:scsns="http://bc.si.retail.ibm.com/POSBCSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://bc.si.retail.ibm.com/POSBCSchema C:\PosBc\POSBCSchema_main.xsd">
//             <InitializeRequest>
//                 <OperatorID>NO_DEFAULT</OperatorID>
//                 <TerminalNumber>900</TerminalNumber>
//                 <Recovery>false</Recovery>
//             </InitializeRequest>
//             </scsns:Initialize>
//             """;

//             Mensaje(mensaje3);

//             // Cerrar el socket
//             //socket.Shutdown(SocketShutdown.Both);
//             //socket.Close();
//         }
//         catch (SocketException e)
//         {
//             Console.WriteLine($"Error de socket: {e.Message}");
//         }
//         catch (Exception e)
//         {
//             Console.WriteLine($"Error: {e.Message}");
//         }
//     }

//     public static void Mensaje(string mensaje)
//     {
//         // Enviar un mensaje al servidor
//         socket.Send(Salida(mensaje));
//         Console.WriteLine($"Mensaje #1 enviado: {mensaje}");

//         Random random = new Random();
//         int delay = random.Next(100, 5001); // Tiempo de espera aleatorio entre 0.1 y 5 segundos
//         Console.WriteLine($"Espera {delay}ms para enviar siguiente mensaje...");
//         Task.Delay(delay).Wait(); // Espera asincrónica
//     }

//     public static void Respuesta()
//     {
//         // Recibir la respuesta del servidor
//         byte[] buffer = new byte[4096];
//         int bytesRead = socket.Receive(buffer);
//         numeroRespuestas++;
//         string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);
//         Console.WriteLine($"Respuesta #{numeroRespuestas} recibida: {response}");
//     }

//     public static async Task EsperarMensajesAsync()
//     {
//         Console.WriteLine("Eperando mensajes...");
//         byte[] buffer = new byte[4096];

//         while (true)
//         {
//             try
//             {
//                 int bytesRead = await socket.ReceiveAsync(buffer, SocketFlags.None);
//                 if (bytesRead > 0)
//                 {
//                     numeroRespuestas++;
//                     string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);
//                     Console.WriteLine($"Respuesta #{numeroRespuestas} recibida: {response}");
//                 }
//             }
//             catch (SocketException e)
//             {
//                 Console.WriteLine($"Error de socket: {e.Message}");
//                 break;
//             }
//             catch (Exception e)
//             {
//                 Console.WriteLine($"Error: {e.Message}");
//                 break;
//             }
//         }
//     }

//     public static byte[] Salida(string trama)
//     {
//         // Codifica longitud del mensaje en los 4 primeros bytes.
//         var longitud = Convert.ToUInt32(trama.Length);
//         byte[] bytesConLongMensaje = BitConverter.GetBytes(longitud);
//         // Bytes mas significativos deben ir primero, usa 'big-endian'.
//         if (BitConverter.IsLittleEndian)
//             Array.Reverse(bytesConLongMensaje);
//         // Codifica en bytes texto del mensaje.
//         byte[] bytesConMensaje = Encoding.UTF8.GetBytes(trama);
//         // Copia los 2 arreglos de bytes en un arreglo unificado.
//         byte[] bytes = new byte[bytesConLongMensaje.Length + bytesConMensaje.Length];
//         Buffer.BlockCopy(bytesConLongMensaje, 0, bytes, 0, bytesConLongMensaje.Length);
//         Buffer.BlockCopy(bytesConMensaje, 0, bytes, bytesConLongMensaje.Length, bytesConMensaje.Length);
//         return bytes;
//     }
// }

public class SocketClientECO
{
    private const int Port = 6697; // Puerto del servidor
    private const string Server = "127.0.0.1"; // Dirección IP del servidor

    public static async Task Main(string[] args)
    {
        try
        {
            using Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            await socket.ConnectAsync(Server, Port);
            Console.WriteLine("Cliente ECO #1 Conectado al servidor.");

            // Enviar 4 mensajes de texto en formato binario
            for (int i = 1; i <= 4; i++)
            {
                string message = $"Mensaje {i} desde el cliente CHEC";

                byte[] bufferMsj = Util.ConvierteEnBufferBytes(message);

                await socket.SendAsync(new ArraySegment<byte>(bufferMsj), SocketFlags.None);
                Console.WriteLine($"Mensaje enviado: {message} espera 1 segundo");
                Task.Delay(1000).Wait();
            }

            // Recibir mensajes de forma asincrónica en un ciclo infinito
            await RecibirMensajes(socket);
        }
        catch (SocketException e)
        {
            Console.WriteLine($"Error de socket: {e.Message}");
        }
        catch (Exception e)
        {
            Console.WriteLine($"Error: {e.Message}");
        }
    }

    private static async Task RecibirMensajes(Socket socket)
    {
        byte[] buffer = new byte[4096];

        while (true)
        {
            int bytesRead = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), SocketFlags.None);
            if (bytesRead > 0)
            {
                // Obtener la longitud del mensaje
                byte[] lengthBytes = new byte[4];
                Array.Copy(buffer, 0, lengthBytes, 0, 4);

                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(lengthBytes);
                }

                int messageLength = BitConverter.ToInt32(lengthBytes, 0);
                string response = Encoding.UTF8.GetString(buffer, 4, messageLength);
                Console.WriteLine($"Respuesta recibida: {response}");
            }
            else
            {
                break; // La conexión se ha cerrado
            }
        }
    }
}

