using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Windows.Forms;
using System.Xml;
using Fleck;
using Microsoft.VisualBasic.ApplicationServices;
using Newtonsoft.Json;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;


public class WebSocketServer
{
    //用户信息
    public static List<ClassUserInfo> IWebSocketUserinfo = new List<ClassUserInfo>();
    //socket信息
    public static List<IWebSocketConnection> _clients = new List<IWebSocketConnection>();
    //课程信息
    public static List<ClassInfo> _classInfos = new List<ClassInfo>();

    public Fleck.WebSocketServer _server;

    public async void Start(string location)
    {

        var certPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "fullchain.pfx");
        if (!File.Exists(certPath))
        {
            MessageBox.Show("证书文件未找到！");
            return;
        }
        var certificate = new X509Certificate2(certPath, "");


        var _server = new Fleck.WebSocketServer(location)
        {
           
            Certificate = certificate,
            EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls12,
            RestartAfterListenError = true
        };

        _server.Start(async socket =>
        {
            socket.OnOpen = () =>
            {

                try
                {
                    Result r = new Result();
                    ClassUserInfo u = new ClassUserInfo();
                    var query = HttpUtility.ParseQueryString(socket.ConnectionInfo.Path);
                    u.UserName = HttpUtility.UrlDecode(query["UserName"]);
                    u.Class = Convert.ToInt64(query["Class"]);
                    u.Schoolclass = Convert.ToInt32(query["SchoolClass"]);
                    u.UserID = Convert.ToInt64(query["UserID"]);
                    u.UserType = Convert.ToInt32(query["UserType"]);//0学生 1老师  2教室
                    u.GUID = socket.ConnectionInfo.Id;
                    string token = query["Token"];
                    u.Linsocket = socket;
                    if (token != "123456")
                    {
                        r.IsSuccess = false;
                        r.Data = "Faile TokenNo";
                        r.MessageType = 0;
                        socket.Send(JsonConvert.SerializeObject(r));
                        return;
                    }
                    else
                    {
                        r.IsSuccess = true;
                        r.Data = "ok";
                        r.MessageType = 0;
                        socket.Send(JsonConvert.SerializeObject(r));
                        IWebSocketUserinfo.Add(u);
                        _clients.Add(socket);

                        //查询课程是否存在 
                        bool exists = _classInfos.Any(c => c.CourseID == u.Class);
                        if (exists)
                        {
                            ClassInfo foundClass = _classInfos.FirstOrDefault(c => c.CourseID == u.Class);
                            if (u.UserType == 1 && u.UserID != 999998)
                            {
                                foundClass.CourseName = u.UserName;
                                foundClass.DisplayID = u.UserID;
                                foundClass.CourseStatus = 1;
                                foundClass.TeacherID = u.UserID;
                                foundClass.TeacherAudioIsOpen = true;
                            }
                            else if (u.UserID == 999998)
                            {
                                foundClass.DisplayID = foundClass.TeacherID;
                            }
                            //找到音频控制文件是否存在
                            if (!foundClass.userAudioStatus.Any(c => c.UserID == u.UserID))
                            {
                                //新加入用户默认静音
                                UserAudioStatus ux = new UserAudioStatus();
                                ux.UserID = u.UserID;
                                //需要判定默认是否是全屏静音状态
                                ux.IsOpen = foundClass.AudioIsOpen;
                                ux.UserType = u.UserType;
                                if (ux.UserType == 1)
                                {
                                    ux.IsOpen = true;
                                }
                                foundClass.userAudioStatus.Add(ux);
                            }
                            else
                            {
                                UserAudioStatus ux = foundClass.userAudioStatus.FirstOrDefault(c => c.UserID == u.UserID);
                                ux.IsOpen = false;
                            }
                        }
                        else
                        {
                            //如果课程不存在则创建一个新的课程 并加入这个用户ID
                            ClassInfo c = new ClassInfo();
                            c.CourseID = u.Class;
                            c.CourseStatus = 0;
                            //c.AudioIsOpen = true;
                            c.AudioIsOpen = true;
                            c.TeacherAudioIsOpen = true;
                            if (u.UserType == 1 && u.UserID != 999998)
                            {
                                c.CourseName = u.UserName;
                                c.DisplayID = u.UserID;
                                c.CourseStatus =1;
                                c.TeacherID = u.UserID;
                            }

                            UserAudioStatus ux = new UserAudioStatus();
                            ux.UserID = u.UserID;
                            ux.IsOpen = true;
                            ux.UserType = u.UserType;
                            if (ux.UserType == 1)
                            {
                                ux.IsOpen = true;
                            }
                            c.userAudioStatus = new List<UserAudioStatus>();
                            c.userAudioStatus.Add(ux);
                            _classInfos.Add(c);
                        }
                        //如果有新用户加入 则需要通知所有客户端 更新用户列表
                        List<ClassUserInfo >lt = IWebSocketUserinfo.Where(c => c.Class == u.Class && c.UserType != 1 && u.UserID != 999999999).ToList();

                        var result = IWebSocketUserinfo.Where(c => c.Class == u.Class );
                        foreach (var c in result)
                         {
                            r = new Result();
                            r.MessageType = 100;
                            r.IsSuccess = true;
                            r.Data = JsonConvert.SerializeObject(lt);
                            c.Linsocket.Send(JsonConvert.SerializeObject(r));
                        }
                    }
                }
                catch { }
            };

            socket.OnClose = () =>
            {
                var query = HttpUtility.ParseQueryString(socket.ConnectionInfo.Path);
                long UserID = Convert.ToInt64(query["UserID"]);
                RemoveUserAudioStatus(_classInfos, UserID);
                IWebSocketUserinfo.RemoveAll(P => P.GUID == socket.ConnectionInfo.Id);
                _clients.Remove(socket);
                //这里需要移除监控用户

            };

            socket.OnMessage =  message =>
            {
                try
                {
                    var user = IWebSocketUserinfo.First(p => p.GUID == socket.ConnectionInfo.Id);
                    OperaterSocketData(message, IWebSocketUserinfo, socket, user);
                }
                catch { 
                
                }
               
            };
        });
    }

    public static void RemoveUserAudioStatus(List<ClassInfo> classInfoX, long userId)
    {
        foreach (ClassInfo classInfo in classInfoX)
        {
            if (classInfo?.userAudioStatus != null)
            {
                classInfo.userAudioStatus.RemoveAll(u => u.UserID == userId);
            }
        }
    }

    //消息处理
    public async void OperaterSocketData(string message, List<ClassUserInfo> ListUser, IWebSocketConnection socket, ClassUserInfo user)
    {
        try
        {
            ReciveSocketInfo recive = JsonConvert.DeserializeObject<ReciveSocketInfo>(message);
            long Lclass=Convert.ToInt64(recive.Class);

            //用户自己关闭声音
            if (recive.Data == "StudentCloseAudio")
            {
                ClassInfo cl = _classInfos.First(c => c.CourseID == Lclass);
                // 将所有IsOpen设置为true
                foreach (var u in cl.userAudioStatus)
                {
                    if (u.UserID ==user.UserID)
                    {
                        u.IsOpen = false;
                    }
                }
                return;
            }

            if (recive.Data == "StudentOpenAudio")
            {

                ClassInfo cl = _classInfos.First(c => c.CourseID == Lclass);
                if (cl.AudioIsOpen == false)
                {
                    Result r = new Result();
                    r.MessageType = 201;
                    r.IsSuccess = true;
                    r.Data = "TeacherCloseAudio";
                    socket.Send(JsonConvert.SerializeObject(r));
                    return;
                }
                else
                {
                    // 将所有IsOpen设置为true
                    foreach (var u in cl.userAudioStatus)
                    {
                        if (u.UserID == user.UserID)
                        {
                            u.IsOpen = true;
                        }
                    }
                }
                   
            }


            if (recive.Data == "GetCourseUserInfo")
            {
                Result r = new Result();
                r.MessageType = 902;
                r.IsSuccess = true;
                r.Data = JsonConvert.SerializeObject(IWebSocketUserinfo.Where(c => c.Class == Convert.ToInt64(recive.Class) && c.UserType != 3));
                socket.Send(JsonConvert.SerializeObject(r));
                return;
            }                                                                                                                       


            if (recive.Data == "GetCourseUserInfo")
            {
                Result r = new Result();
                r.MessageType = 902;
                r.IsSuccess = true;
                r.Data = JsonConvert.SerializeObject(IWebSocketUserinfo.Where(c => c.Class == Convert.ToInt64(recive.Class) && c.UserType != 3));
                socket.Send(JsonConvert.SerializeObject(r));
                return;
            }


            if (recive.Data == "MasterScreenOpen")
            {
                if (IWebSocketUserinfo.Any(c => c.Class == Lclass && c.UserType == 1 && c.UserID != 999998))
                {
                    _classInfos.First(c => c.CourseID == Lclass).CourseName = IWebSocketUserinfo.First(c => c.Class == Lclass && c.UserType == 1 && c.UserID != 999998).UserName;
                    _classInfos.First(c => c.CourseID == Lclass).DisplayID = IWebSocketUserinfo.First(c => c.Class == Lclass && c.UserType == 1 && c.UserID != 999998).UserID;
                }
                else {
                    _classInfos.First(c => c.CourseID == Lclass).DisplayID = 0;
                    Result r = new Result();
                    r.MessageType = 905;
                    r.IsSuccess = true;
                    r.Data ="SettingMasterScreenFalse";
                    socket.Send(JsonConvert.SerializeObject(r));
                }
            }

            //如果是取信息 获取用户信息
            if (recive.Data == "GetUserInfo")
            {
                Result r = new Result();
                r.MessageType = 102;
                r.IsSuccess = true;
                r.Data = JsonConvert.SerializeObject(IWebSocketUserinfo.Where(c => c.Class == Convert.ToInt64(recive.Class) && c.UserType != 1));
                socket.Send(JsonConvert.SerializeObject(r));
                return;
            }
            //获取课程信息
            if (recive.Data == "GetCourseInfo")
            {
                Result r = new Result();
                r.MessageType = 101;
                r.IsSuccess = true;
                r.Data = JsonConvert.SerializeObject(_classInfos.First(c => c.CourseID == Convert.ToInt64(recive.Class)));
                socket.Send(JsonConvert.SerializeObject(r));
                return;
            }

            //全部开启声音  --继续走流程
            if (recive.Data == "AllAudioOpen") 
            {
                ClassInfo cl = _classInfos.First(c => c.CourseID == Convert.ToInt64(recive.Class));
                cl.AudioIsOpen = true;
                // 将所有IsOpen设置为true
                foreach (var u in cl.userAudioStatus)
                {
                    if (u.UserID != 999998)
                    {
                        u.IsOpen = true;
                    }
                }
            }

            //全部关闭声音 --继续走流程
            if (recive.Data == "AllAudioClose")
            {
                ClassInfo cl = _classInfos.First(c => c.CourseID == Convert.ToInt64(recive.Class));
                cl.AudioIsOpen = false;
                // 将所有IsOpen设置为true
                foreach (var u in cl.userAudioStatus)
                {
                    if (u.UserID != 999998)
                    {
                        u.IsOpen = false;
                    }
                 
                }
            }

            // 全部开启声音--继续走流程
            if (recive.Data == "AudioOpen")
            {
                ClassInfo cl = _classInfos.First(c => c.CourseID == Convert.ToInt64(recive.Class));
                foreach (var u in cl.userAudioStatus)
                {
                    if (u.UserID != 999998 & u.UserID == recive.UserID)
                    {
                        u.IsOpen = true;
                    }
                }
                cl.AudioIsOpen = true;
            }

            //全部关闭声音 --继续走流程
            if (recive.Data == "AudioClose")
            {
                ClassInfo cl = _classInfos.First(c => c.CourseID == Convert.ToInt64(recive.Class));
                foreach (var u in cl.userAudioStatus)
                {
                    if (u.UserID != 999998 & u.UserID == recive.UserID)
                    {
                        u.IsOpen = false;
                    }
                }
            }
            


            //开始上课
            if (recive.Data == "StartClass")
            {
                ClassInfo cl = _classInfos.First(c => c.CourseID == Convert.ToInt64(recive.Class));
                cl.CourseStatus = 1;
                cl.AudioIsOpen = true;
                try
                {
                    cl.CourseName = IWebSocketUserinfo.First(c => c.UserType == 1 && c.UserID != 999998).UserName;//课程附上教师名字
                    //cl.DisplayID = IWebSocketUserinfo.First(c => c.UserType == 1 && c.UserID != 999998&&c.UserID==).UserID;//得到用户视频音频ID
                    cl.DisplayID = user.UserID;//得到用户视频音频ID
                }
                catch { }
               
                Result r = new Result();
                r.MessageType = 103; 
                r.IsSuccess = true;
                if (!IWebSocketUserinfo.Any(c => c.UserType == 1 && c.UserID != 999998 && c.Class == Convert.ToInt64(recive.Class)))
                {
                    r.Data = "NoTeacher";
                    cl.CourseStatus = 0;
                    socket.Send(JsonConvert.SerializeObject(r));
                }
                else
                { 
                     
                }
            }
            //结束上课
            if (recive.Data == "EndClass")
            {
                ClassInfo cl = _classInfos.First(c => c.CourseID == Convert.ToInt64(recive.Class));
                cl.DisplayID = 0;
                cl.CourseStatus = 0;
                cl.AudioIsOpen = false;
            }
            //开启监控某一个画面
            if (recive.Data.IndexOf("StudentJK_")>-1)
            {
                string[] dataList = recive.Data.Replace("StudentJK_", "").Split('_');
                long jkID = Convert.ToInt64(dataList[0]);
                long classID = Convert.ToInt64(dataList[1]);
                string userName = IWebSocketUserinfo.First(C => C.UserID == jkID).UserName;
                DisplayJK dsJK = new DisplayJK();
                dsJK.UserID = jkID;
                dsJK.Name = userName;
                var ClassInfoT= _classInfos.First(C => C.CourseID == classID);
                if (ClassInfoT.DisplayJK == null)
                {
                    ClassInfoT.DisplayJK = new List<DisplayJK>();
                    ClassInfoT.DisplayJK.Add(dsJK);
                }
                else
                {
                    if (!ClassInfoT.DisplayJK.Any(c => c.UserID == jkID))
                    {
                        ClassInfoT.DisplayJK.Add(dsJK);
                    }
                }
            }



            //取消某一个监控画面
            if (recive.Data.IndexOf("QXJK_") > -1)
            {
                string[] dataList = recive.Data.Replace("QXJK_", "").Split('_');
                long jkID = Convert.ToInt64(dataList[0]);
                long classID = Convert.ToInt64(dataList[1]);
                string userName = IWebSocketUserinfo.First(C => C.UserID == jkID).UserName;
                DisplayJK dsJK = new DisplayJK();
                dsJK.UserID = jkID;
                dsJK.Name = userName;
                var ClassInfoT = _classInfos.First(C => C.CourseID == classID);
                var target = ClassInfoT.DisplayJK.FirstOrDefault(c => c.UserID == jkID);
                if (target != null)
                {
                    ClassInfoT.DisplayJK.Remove(target);
                }
            }
            if (recive.Data.IndexOf("ScreenSharing_") > -1)
            {
                if (IWebSocketUserinfo.Any(c => c.Class == Lclass && c.UserType == 1 && c.UserID != 999998))
                {
                    string[] dataList = recive.Data.Replace("ScreenSharing_", "").Split('_');
                    long UserID = Convert.ToInt64(dataList[1].Trim());
                    long CourseID = Lclass;
                    _classInfos.First(c => c.CourseID == CourseID).DisplayID = UserID;
                }
                else
                {
                    _classInfos.First(c => c.CourseID == Lclass).DisplayID = 0;
                    Result r = new Result();
                    r.MessageType = 906;
                    r.IsSuccess = true;
                    r.Data = "SettingMasterScreenFalse";
                    socket.Send(JsonConvert.SerializeObject(r));
                    return;
                }

            }
            //设置为主屏幕
            if (recive.Data.IndexOf("StudentMasterScreen_") > -1)
            {
         
                string[] dataList = recive.Data.Replace("StudentMasterScreen_", "").Split(',');
                long UserID = Convert.ToInt64(dataList[0]);
                long ClassID = Convert.ToInt64(dataList[1]);


                ////清空所有监控
                //var ClassInfoT = _classInfos.First(C => C.CourseID == ClassID);
                //ClassInfoT.DisplayJK.Clear();

                DisplayJK dsJK = new DisplayJK();
                dsJK.UserID = UserID;
                string userName = IWebSocketUserinfo.First(C => C.UserID == UserID).UserName;
                dsJK.Name = userName;
                //if (ClassInfoT.DisplayJK == null || ClassInfoT.DisplayJK.Count == 0)
                //{
                //    ClassInfoT.DisplayJK = new List<DisplayJK>();
                //    ClassInfoT.DisplayJK.Add(dsJK);
                //}
                //_classInfos.First(c => c.CourseID == ClassID).DisplayJK = ClassInfoT.DisplayJK;
                _classInfos.First(c => c.CourseID == ClassID).CourseName = userName;
                _classInfos.First(c => c.CourseID == ClassID).DisplayID = UserID;
            }

            //检查教师是否存在
            if (recive.Data.IndexOf("CheckTeacherIsOnline") > -1)
            {
                if (IWebSocketUserinfo.Any(c => c.Class == Lclass && c.UserType == 1 && c.UserID != 999998))
                {
                    Result r = new Result();
                    r.MessageType = 907;
                    r.IsSuccess = true;
                    r.Data = "";
                    socket.Send(JsonConvert.SerializeObject(r));
                    return;
                }
                else {
                    Result r = new Result();
                    r.MessageType = 908;
                    r.IsSuccess = true;
                    r.Data = "";
                    socket.Send(JsonConvert.SerializeObject(r));
                    return;
                }
            }

            

            //踢出用户
            if (recive.Data == "KickOut")
            {

                string x = "000";
            }

            //关闭教师声音
            if (recive.Data == "CloseTeacherAudio")
            {
                _classInfos.First(c => c.CourseID == Convert.ToInt64(recive.Class)).TeacherAudioIsOpen=false;
            }

            //开启教师声音
            if (recive.Data == "OpenTeacherAudio")
            {
                _classInfos.First(c => c.CourseID == Convert.ToInt64(recive.Class)).TeacherAudioIsOpen = true;
        
            }


            // 群发
            if (recive.Type == 1)
            {
                SendDataOtherUser(recive, ListUser, user);
            }
            //单发
            if (recive.Type == 0)
            {
                SendDataUserToUser(recive, ListUser, user);
            }
        }
        catch { 
        
        }
    }
    //如果是发单人

    public async void SendDataOtherUser(ReciveSocketInfo recive, List<ClassUserInfo> ListUser, ClassUserInfo user)
    {
        string userIDList = recive.UserIDS;
        if (!string.IsNullOrEmpty(userIDList))
        {
            string[] userids = userIDList.Trim().Split(',');

            foreach (ClassUserInfo c in ListUser)
            {
                foreach (string userID in userids)
                {
                    if (c.UserID == Convert.ToInt64(userID)&&c.UserType == recive.UserType)
                    {
                        c.Linsocket.Send(recive.Data);
                    }
                }
            }
        }
        string rclass = recive.Class;
        if (!string.IsNullOrEmpty(rclass))
        {
            string[] rclasslist = rclass.Trim().Split(',');

            foreach (ClassUserInfo c in ListUser)
            {
                foreach (string r in rclasslist)
                {

                    if (c.Class == Convert.ToInt64(r) && c.UserType == recive.UserType)
                    {
                        c.Linsocket.Send(recive.Data);
                    }
                }
            }
        }

        string rschoolclass = recive.SchoolClass;
        if (!string.IsNullOrEmpty(rschoolclass))
        {
            string[] rschoolclasslist = rschoolclass.Trim().Split(',');

            foreach (ClassUserInfo c in ListUser)
            {
                foreach (string r in rschoolclasslist)
                {

                    if (c.Schoolclass == Convert.ToInt64(r) && c.UserType == recive.UserType)
                    {
                        c.Linsocket.Send(recive.Data);
                    }
                }
            }
        }
    }


    private async void SendDataUserToUser(ReciveSocketInfo recive, List<ClassUserInfo> ListUser, ClassUserInfo user)
    {
        foreach (ClassUserInfo c in ListUser)
        {
            if (c.UserID == recive.UserID && c.UserType == recive.UserType)
            {
                c.Linsocket.Send(recive.Data);
            }
        }
    }

    private  void CloseWindow(ReciveSocketInfo recive, List<ClassUserInfo> ListUser, ClassUserInfo user) {
        string[] listClass = recive.Class.Trim(',').Split(',');
        ReciveSocketInfo rsi = new ReciveSocketInfo();
        Result r = new Result();
        r.IsSuccess = true;
        r.MessageType = 1;
        r.Data = "CloseWindow";
        //处理业务逻辑
        foreach (string cl in listClass)
        {               
            //给符合条件的机器发消息
            List<ClassUserInfo> result = ListUser.Where(item => item.Class == Convert.ToInt32(cl)).ToList();
            foreach (ClassUserInfo c in result)
            {
                if (c != user)
                {
                    try
                    {
                         c.Linsocket.Send(JsonConvert.SerializeObject(r));
                    }
                    catch
                    {
                        ListUser.Remove(c);
                    }
                }
            }
        }
    }


    public void Stop()
    {
        foreach (var client in _clients.ToList())
        {
            client.Close();
        }
        _clients.Clear();
        // Console.WriteLine("WebSocket 服务器已停止");
    }
}
