public async Task ConnectToRemoteUser(string remoteIpAddress, int remotePortNumber)
        {
            Console.WriteLine("STATUS: Connecting to remote user");
            State  = ConnectionState.Connecting;
            Sender = await NetworkService.ConnectToRemoteAsync(Sender, remoteIpAddress, remotePortNumber);

            if (Sender != null)
            {
                Console.WriteLine($"RESULT: Connection to {((IPEndPoint)Sender.RemoteEndPoint).Address} established");
            }
            else
            {
                Console.WriteLine("RESULT: Connection to remote failed");
                Sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                State  = ConnectionState.Listening;
                InfoDisplay.Show("Could not connect to user");
                return;
            }

            Console.WriteLine("STATUS: Sending request data to remote user");
            NetworkData request = new NetworkData(LocalUser, NetworkDataType.Request);
            bool        sent    = await NetworkService.SendDataAsync(Sender, request);

            if (sent)
            {
                Console.WriteLine("RESULT: Sending of request data successful");
            }
            else
            {
                Console.WriteLine("RESULT: Sending of request data failed");
                Sender.Shutdown(SocketShutdown.Both);
                InfoDisplay.Show("Could not send request to user");
                State = ConnectionState.Listening;
            }
        }
        private void ProcessResponse(NetworkData networkData)
        {
            Console.WriteLine("STATUS: Processing response");
            Console.WriteLine($"RESULT: Received a response of type {networkData.ResponseType}");

            switch (networkData.ResponseType)
            {
            case ResponseType.Exit:
                ConnectionState tempState = State;
                State = ConnectionState.Listening;
                if (tempState == ConnectionState.Chatting)
                {
                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        ExitChat();
                    });
                    InfoDisplay.Show($"{RemoteUser.UserName} left the chat");
                }
                else
                {
                    InfoDisplay.Show($"{RemoteUser.UserName} canceled their chat request");
                }
                break;

            case ResponseType.Accept:
                State = ConnectionState.Chatting;
                InfoDisplay.Show($"{RemoteUser.UserName} accepted your chat request");
                break;

            case ResponseType.Decline:
                State = ConnectionState.Listening;
                InfoDisplay.Show($"{RemoteUser.UserName} declined your chat request");
                break;

            case ResponseType.Buzz:
                if (State == ConnectionState.Chatting)
                {
                    System.Media.SystemSounds.Beep.Play();
                }
                break;

            case ResponseType.Disconnect:
                ConnectionState prevState = State;
                State = ConnectionState.Listening;
                if (prevState == ConnectionState.Chatting)
                {
                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        ExitChat();
                    });
                }
                InfoDisplay.Show($"{RemoteUser.UserName} disconnected from application");
                break;

            case ResponseType.None:
                Console.WriteLine("ERROR: Network data is not a response");
                break;
            }
        }
 private void ProcessMessage(NetworkData networkData)
 {
     Console.WriteLine($"STATUS: Processing message of type {networkData.DataType}");
     Application.Current.Dispatcher.Invoke(() =>
     {
         AddRemoteMessage(networkData);
     });
 }
        private async Task ListenForRemoteConnection()
        {
            bool listening = true;

            Console.WriteLine("STATUS: Listening for a connection");

            while (listening)
            {
                Receiver = await NetworkService.AcceptConnectionAsync(Listener);

                if (Receiver != null)
                {
                    Console.WriteLine($"RESULT: Connection request from {((IPEndPoint) Receiver.RemoteEndPoint).Address} accepted");
                }
                else
                {
                    Console.WriteLine("RESULT: Accept of connection failed");
                    Receiver = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                }

                if (Receiver != null && Receiver.Connected)
                {
                    Console.WriteLine("STATUS: Waiting to receive request data");
                    NetworkData networkData = await NetworkService.ReceiveDataAsync(Receiver);

                    if (networkData != null && networkData.DataType == NetworkDataType.Request)
                    {
                        Console.WriteLine($"RESULT: Received request data from {networkData.User.UserName}");
                        RemoteUser = networkData.User;
                        listening  = false;
                    }
                    else
                    {
                        Console.WriteLine("RESULT: Receive of request data failed");
                        Receiver.Shutdown(SocketShutdown.Both);
                    }

                    if (!Sender.Connected)
                    {
                        await ConnectToRemoteUser(RemoteUser.IpAddress, RemoteUser.PortNumber);

                        State = ConnectionState.Responding;
                    }
                    else
                    {
                        State = ConnectionState.Waiting;
                    }
                }
                else
                {
                    Console.WriteLine("STATUS: Listening for connection canceled");
                    listening = false;
                }
            }
        }
        public async Task ReceiveNetworkData()
        {
            if (State == ConnectionState.Listening ||
                State == ConnectionState.Connecting)
            {
                Console.WriteLine("ERROR: Not ready to receive network data");
                return;
            }

            bool        receiving   = true;
            NetworkData networkData = null;

            while (receiving)
            {
                Console.WriteLine("STATUS: Waiting to receive network data");
                networkData = await NetworkService.ReceiveDataAsync(Receiver);

                if (networkData != null && networkData.DataType == NetworkDataType.Response)
                {
                    Console.WriteLine($"RESULT: Received response data from {networkData.User.UserName}");
                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        ProcessResponse(networkData);
                    });
                }
                else if (networkData != null && (networkData.DataType == NetworkDataType.Message ||
                                                 networkData.DataType == NetworkDataType.Image))
                {
                    Console.WriteLine($"RESULT: Received message data from {networkData.User.UserName}");
                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        ProcessMessage(networkData);
                    });
                }
                else if (networkData != null && networkData.DataType == NetworkDataType.Request)
                {
                    Console.WriteLine("RESULT: Wrong type of data received");
                }
                else
                {
                    Console.WriteLine("RESULT: Receiving of network data failed");
                    receiving = false;
                }

                if (State == ConnectionState.Listening ||
                    State == ConnectionState.Connecting)
                {
                    Console.WriteLine("STATUS: Receiving of network data canceled");
                    receiving = false;
                }
            }
        }
        public async Task SendNetworkData(NetworkData networkData)
        {
            Console.WriteLine("STATUS: Trying to send network data");
            if (Sender != null && Sender.Connected)
            {
                Console.WriteLine($"STATUS: Sending network data of type {networkData.DataType} to remote user");
                bool sent = await NetworkService.SendDataAsync(Sender, networkData);

                if (sent)
                {
                    Console.WriteLine("RESULT: Sending of network data successful");
                }
                else
                {
                    Console.WriteLine("RESULT: Sending of network data failed");
                }
            }
            else
            {
                Console.WriteLine("RESULT: Sender has no connection");
            }
        }