using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

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

namespace SocketStudy.ServerApp
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        //服务监听
        private TcpListener _tcpServer = null;

        //存放活动客户端连接字典
        private ConcurrentDictionary<string, TcpClient> _remoteClientDic = new ConcurrentDictionary<string, TcpClient>();

        //监听线程
        private Thread _listenerThread;

        public MainWindow()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 窗口呈现完毕事件
        /// </summary>
        private void Window_ContentRendered(object sender, EventArgs e)
        {
            //初始化客户端
            comboBox_Clients.Items.Clear();
            comboBox_Clients.Items.Insert(insertIndex: 0,"广播");
            comboBox_Clients.SelectedIndex = 0;

            //默认服务器网址
            comboBox_ServerAddress.Items.Insert(0, "本机所有IP4");
            comboBox_ServerAddress.SelectedIndex = 0;

            var ip4Addresses = Dns.GetHostAddresses(Dns.GetHostName(), AddressFamily.InterNetwork) ?? new IPAddress[] { IPAddress.Any};
            foreach (var ip in ip4Addresses)
            { 
                comboBox_ServerAddress.Items.Add(ip);
            }
        }

        /// <summary>
        /// 启动服务
        /// </summary>
        private void btn_Start_Click(object sender, RoutedEventArgs e)
        {
            if (_tcpServer?.Server?.IsBound ?? false)
            {
                WriteLog("服务正在运行,无需启动!");
                return;
            }

            IPAddress serverAddress = IPAddress.Any;

            if (comboBox_ServerAddress.SelectedValue.ToString() != "本机所有IP4")
            {
                serverAddress = (IPAddress)comboBox_ServerAddress.SelectedValue;
            }

            int serverPort = 6605;
            if (!int.TryParse(textBox_ServerPort.Text.Trim(), out serverPort))
            {
                WriteLog("端口号错误");
                return;
            }
            else
            {
                if (serverPort <= 1024 || serverPort >= 65535)
                {
                    WriteLog("端口号错误:必须在 1205-65534");
                    return;
                }
            }

            WriteLog("启动服务...");
            _tcpServer = new TcpListener(serverAddress, serverPort);
            _tcpServer.Start();

            WriteLog("服务成功启动!");

            //开启监听线程
            _listenerThread = new Thread(AcceptTcpClient);
            _listenerThread.IsBackground = true;
            _listenerThread.Start(_tcpServer);

            //控件操作
            comboBox_ServerAddress.IsEnabled = false;
            textBox_ServerPort.IsEnabled = false;

            WriteLog("服务启动完毕!");
        }

        /// <summary>
        /// 停止服务
        /// </summary>
        private void btn_Stop_Click(object sender, RoutedEventArgs e)
        {
            if (_tcpServer == null || _tcpServer.Server.IsBound == false)
            {
                WriteLog("服务正未运行,无法停止!");
                return;
            }

            //关闭客户端
            foreach (var item in _remoteClientDic)
            {
                if (item.Value.Connected)
                {
                    item.Value.Close();
                    item.Value.Dispose();
                }
            }

            WriteLog("停止服务...");
            _tcpServer?.Stop();

            //清空客户端
            _remoteClientDic.Clear();
            ResetClientsItems();
            

            //恢复控制状态
            comboBox_ServerAddress.IsEnabled = true;
            textBox_ServerPort.IsEnabled = true;

            WriteLog("服务停止完成!");
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        private void btn_Send_Click(object sender, RoutedEventArgs e)
        {
            if (_remoteClientDic.Count == 0 || comboBox_Clients.Items.Count ==0)
            {
                WriteLog("没有正在连接的客户端,请先使用客户端连接到本服务器!");
                return;
            }

            var clientForSend=new List<TcpClient>();

            var selectedItemValue = comboBox_Clients.SelectedValue as string;
            if (selectedItemValue == "广播")
            {
                clientForSend = _remoteClientDic.Where(q => q.Value.Connected == true).Select(d => d.Value).ToList();
            }
            else
            {
                var queryItem = _remoteClientDic.FirstOrDefault(q => q.Key == comboBox_Clients.SelectedValue.ToString());

                clientForSend.Add(queryItem.Value);
            }

            foreach (var client in clientForSend)
            {
                try
                {
                    var message = textBox_SendData.Text.Trim();
                    byte[] buffer = Encoding.UTF8.GetBytes(message);
                    NetworkStream networkStream = client.GetStream();
                    networkStream.Write(buffer, 0, buffer.Length);

                    WriteLog($"发送数据成功:{message}");
                }
                catch (Exception ex)
                {
                    WriteLog($"{ex.Message}");
                }
                finally
                {

                }
            }
        }

        /// <summary>
        /// 写日志信息
        /// </summary>
        private void WriteLog(string message)
        {
            Dispatcher.BeginInvoke(new Action(() =>
            {
                richTextBox_Log.AppendText($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} {message}{System.Environment.NewLine}");
                richTextBox_Log.ScrollToEnd();
                Console.WriteLine(message);
            }));
        }

        /// <summary>
        /// 重新设置客户端列表项
        /// </summary>
        private void ResetClientsItems()
        {
            Dispatcher.BeginInvoke(new Action(() =>
           {
               //字典中的远程客户端同步到下拉列表项
               foreach (var clientItem in _remoteClientDic)
               {
                   if (!comboBox_Clients.Items.Contains(clientItem.Key))
                   {
                       comboBox_Clients.Items.Add(clientItem.Key);
                   }
               }

               //从下拉项中移除已经下线的远程客户端
               for (int i = 0; i < comboBox_Clients.Items.Count; i++)
               {
                   var itemValue = comboBox_Clients.Items[i] as string;

                   if (itemValue == null)
                   {
                       continue;
                   }

                   if (itemValue.Contains("广播"))
                   {
                       continue;
                   }

                   if (!_remoteClientDic.ContainsKey(itemValue))
                   {
                       comboBox_Clients.Items.Remove(comboBox_Clients.Items[i]);
                   }
               }
           }));
        }

        /// <summary>
        /// 监听客户端连接方法
        /// </summary>
        private void AcceptTcpClient(Object? tcpListener)
        {
            TcpListener? tcpServer = tcpListener as TcpListener;

            if (tcpServer == null)
            {
                WriteLog("调用监听连接方法时,参数为null,将监听不到客户端连接!");
                return;
            }

            WriteLog("开始监听客户端连接...");
            //无限循环:处理多个客户端连接
            while (_tcpServer.Server.IsBound)
            {
                TcpClient remoteClientSocket = null;
                try
                {
                    //阻塞等待操作
                    remoteClientSocket = _tcpServer.AcceptTcpClient();
                    WriteLog("接收到连接请求...");

                    var remoteEndPoint = remoteClientSocket.Client.RemoteEndPoint as IPEndPoint;
                    if (remoteEndPoint == null)
                    {
                        continue;
                    }

                    string ipAndPortKey = $"{remoteEndPoint.Address}:{remoteEndPoint.Port}";

                    if (!_remoteClientDic.ContainsKey(ipAndPortKey))
                    {
                        _remoteClientDic.TryAdd(ipAndPortKey, remoteClientSocket);
                    }

                    ResetClientsItems();

                    //接收数据线程
                    Thread receviceThread = new Thread(ReciveData);
                    receviceThread.IsBackground = true;
                    receviceThread.Start(remoteClientSocket);

                    WriteLog("连接请求处理完成!");
                }
                catch (SocketException socketException)
                {
                    //移除客户端
                    remoteClientSocket?.Close();
                    remoteClientSocket?.Dispose();

                    WriteLog($"出现Socket异常:{socketException.Message}");
                }
                catch (Exception ex)
                {
                    //移除客户端
                    remoteClientSocket?.Close();
                    remoteClientSocket?.Dispose();

                    WriteLog($"出现异常:{ex.Message}");
                }
                finally
                {
                }
            }

            //清空客户端
            _remoteClientDic.Clear();
            ResetClientsItems();

            WriteLog($"监听客户端连接的线程,退出!线程托管Id={Thread.CurrentThread.ManagedThreadId}");
        }

        /// <summary>
        ///  接收客户端数据方法
        /// </summary>
        private void ReciveData(object? tcpClient)
        {
            if (tcpClient == null)
            {
                WriteLog($"接收数据出错:客户端参数{nameof(tcpClient)}为 null");
                return;
            }

            TcpClient remoteClient = (TcpClient)tcpClient;
            IPEndPoint? remoteEndPoint = remoteClient.Client?.RemoteEndPoint as IPEndPoint;
            string remoteClientKey = $"{remoteEndPoint?.Address}:{remoteEndPoint?.Port}";

            try
            {
                while (remoteClient.Connected)
                {
                    NetworkStream remoteClientStream = remoteClient.GetStream();
                    byte[] buffer = new byte[8096];

                    //阻塞等待操作
                    var readCount = remoteClientStream.Read(buffer, 0, buffer.Length);

                    //为0代表客户端主动发送关闭操作数据。平常时,即使发送0长度数据也不会是0
                    if (readCount == 0)
                    {
                        remoteClientStream.Close();
                        remoteClientStream.Dispose();

                        WriteLog($"接收[{remoteClientKey}]关闭连接请求数据。");
                        break;
                    }
                    var message = Encoding.UTF8.GetString(buffer, 0, readCount);
                    WriteLog($"接收到[{remoteClientKey}]数据:{message}");
                }
            }
            catch (SocketException socketException)
            {
                WriteLog($"接收到[{remoteClientKey}]数据异常:{socketException.Message}");
            }
            catch (Exception ex)
            {
                WriteLog($"接收到[{remoteClientKey}]数据异常:{ex.Message}");
            }
            finally
            {
                remoteClient.Close();
                remoteClient.Dispose();

                _remoteClientDic.Remove(remoteClientKey, out var sss);
                ResetClientsItems();

                WriteLog($"接收[{remoteClientKey}]数据的线程退出:线程托管Id={Thread.CurrentThread.ManagedThreadId}");
            }
        }
    }
}