public async Task SendUserListUpdate(Chat ChatUpdate)
        {
            if (ChatUpdate?.ChatID == null)
            {
                return;
            }
            var sockets  = AllSockets.FindAll(sock => sock?.CurrentChat?.ChatID == ChatUpdate.ChatID);
            var userList = new List <string>();

            foreach (var socket in sockets)
            {
                userList.Add(socket.CurrentUser.DisplayName);
            }
            if (userList.Count == 0)
            {
                return;
            }
            var request = new
            {
                Type  = "UserListUpdate",
                Users = userList
            };

            foreach (var socket in sockets)
            {
                await socket.SendJSON(request);
            }
        }
        public async Task JoinChat(Chat ChatJoin)
        {
            var sockets = AllSockets.FindAll(sock => sock?.CurrentChat?.ChatID == ChatJoin.ChatID);
            var request = new
            {
                Type        = "UserJoined",
                DisplayName = CurrentUser.DisplayName
            };

            foreach (var socket in sockets)
            {
                await socket.SendJSON(request);
            }
        }
        public async Task BroadcastMessage(dynamic Message)
        {
            if (CurrentChat?.ChatID == null)
            {
                return;
            }
            var sockets  = AllSockets.FindAll(sock => sock?.CurrentChat?.ChatID == CurrentChat.ChatID && sock?.CurrentUser?.Username != CurrentUser.Username);
            var userList = new List <string>();

            foreach (var socket in sockets)
            {
                userList.Add(socket.CurrentUser.DisplayName);
            }
            foreach (var socket in sockets)
            {
                await socket.SendJSON(Message);
            }
        }
        public async Task ParseMessage(WebSocketReceiveResult Result, byte[] Buffer)
        {
            if (!Result.EndOfMessage)
            {
                return;
            }
            if (Result.MessageType == WebSocketMessageType.Text)
            {
                var trimmedString = Encoding.UTF8.GetString(Utilities.TrimBytes(Buffer));
                var expando       = JsonConvert.DeserializeObject <ExpandoObject>(trimmedString);
                var jsonMessage   = (dynamic)expando;

                switch ((string)jsonMessage.Type)
                {
                case "GetGuestChat":
                {
                    var displayName = Utilities.GetRandomUserName();
                    CurrentUser = new User()
                    {
                        Username    = User.GetNewUsername(),
                        DisplayName = displayName,
                        AccountType = Utilities.Permanence.Temporary
                    };
                    CurrentUser.AuthenticationTokens.Add(Guid.NewGuid().ToString());
                    CurrentChat = new Chat()
                    {
                        ChatID       = Chat.GetNewID(),
                        OwnerName    = CurrentUser.Username,
                        ChatName     = Utilities.GetRandomChatName(),
                        ChatType     = Utilities.Permanence.Temporary,
                        IsMemberOnly = false
                    };
                    CurrentUser.OwnedChats.Add(CurrentChat.ChatID);
                    var request = new
                    {
                        Type   = "GetGuestChat",
                        Status = "ok",
                        User   = this.CurrentUser,
                        Chat   = this.CurrentChat
                    };
                    await SendJSON(request);

                    CurrentUser.Save();
                    CurrentChat.Save();
                    await JoinChat(this.CurrentChat);
                    await SendUserListUpdate(this.CurrentChat);

                    break;
                }

                case "TryResumeLogin":
                {
                    var user = User.Load((string)jsonMessage.Username);
                    if (await AuthenticateUser(user, jsonMessage) == false)
                    {
                        return;
                    }
                    CurrentUser = user;
                    var chatList = GetChatList();
                    var request  = new
                    {
                        Type                = "TryResumeLogin",
                        Status              = "ok",
                        DisplayName         = CurrentUser.DisplayName,
                        AccountType         = CurrentUser.AccountType,
                        Chats               = chatList,
                        AuthenticationToken = CurrentUser.AuthenticationTokens.Last()
                    };
                    await SendJSON(request);

                    break;
                }

                case "JoinChat":
                {
                    Chat chat = Chat.Load(jsonMessage.ChatID);
                    var  user = User.Load((string)jsonMessage.Username);
                    if (chat == null)
                    {
                        jsonMessage.Status = "not found";
                        await SendJSON(jsonMessage);

                        return;
                    }
                    if (user == null)
                    {
                        var displayName = Utilities.GetRandomUserName();
                        CurrentUser = new User()
                        {
                            Username    = User.GetNewUsername(),
                            DisplayName = displayName,
                            AccountType = Utilities.Permanence.Temporary
                        };
                        CurrentUser.AuthenticationTokens.Add(Guid.NewGuid().ToString());
                    }
                    else
                    {
                        if (await AuthenticateUser(user, jsonMessage) == false)
                        {
                            return;
                        }
                    }
                    if (chat.IsMemberOnly && chat.OwnerName != CurrentUser.Username && !chat.MemberList.Contains(CurrentUser.Username) && !chat.AdminList.Contains(CurrentUser.Username))
                    {
                        jsonMessage.Status = "unauthorized";
                        await SendJSON(jsonMessage);

                        return;
                    }
                    CurrentChat = chat;
                    CurrentUser.InvitedChats.Add(chat.ChatID);
                    CurrentUser.Save();
                    CurrentChat.Save();
                    var chatList = GetChatList();
                    var request  = new
                    {
                        Type                = "JoinChat",
                        Status              = "ok",
                        DisplayName         = CurrentUser.DisplayName,
                        AccountType         = CurrentUser.AccountType,
                        Username            = CurrentUser.Username,
                        Chats               = chatList,
                        Chat                = chat,
                        AuthenticationToken = CurrentUser.AuthenticationTokens.Last()
                    };
                    await SendJSON(request);
                    await JoinChat(chat);
                    await SendUserListUpdate(chat);

                    SendChatHistory(DateTime.Now);
                    break;
                }

                case "ChangeChat":
                {
                    Chat chat = Chat.Load(jsonMessage.ChatID);
                    if (chat == null)
                    {
                        jsonMessage.Status = "not found";
                        await SendJSON(jsonMessage);

                        return;
                    }
                    if (chat.IsMemberOnly && chat.OwnerName != CurrentUser.Username && !chat.MemberList.Contains(CurrentUser.Username) && !chat.AdminList.Contains(CurrentUser.Username))
                    {
                        jsonMessage.Status = "unauthorized";
                        await SendJSON(jsonMessage);

                        return;
                    }
                    var oldChat = CurrentChat;
                    if (oldChat != null)
                    {
                        await LeaveChat(oldChat);
                    }
                    CurrentChat          = chat;
                    jsonMessage.Status   = "ok";
                    jsonMessage.ChatName = chat.ChatName;
                    await SendJSON(jsonMessage);
                    await JoinChat(CurrentChat);

                    if (oldChat != null)
                    {
                        await SendUserListUpdate(oldChat);
                    }
                    await SendUserListUpdate(CurrentChat);

                    SendChatHistory(DateTime.Now);
                    break;
                }

                case "NewChat":
                {
                    if (CurrentUser == null)
                    {
                        return;
                    }
                    var newChat = new Chat()
                    {
                        ChatID       = Chat.GetNewID(),
                        ChatName     = Utilities.GetRandomChatName(),
                        OwnerName    = CurrentUser.Username,
                        ChatType     = CurrentUser.AccountType,
                        IsMemberOnly = false
                    };
                    CurrentUser.OwnedChats.Add(newChat.ChatID);
                    newChat.Save();
                    CurrentUser.Save();
                    CurrentChat        = newChat;
                    jsonMessage.Status = "ok";
                    jsonMessage.Chat   = newChat;
                    await SendJSON(jsonMessage);

                    break;
                }

                case "ChatMessage":
                {
                    string unencoded = Encoding.UTF8.GetString(Convert.FromBase64String(jsonMessage.Message));
                    if (unencoded.StartsWith("/"))
                    {
                        await ParseCommand(unencoded);

                        return;
                    }
                    jsonMessage.TimeStamp   = DateTime.Now;
                    jsonMessage.DisplayName = CurrentUser.DisplayName;
                    jsonMessage.Username    = CurrentUser.Username;
                    await BroadcastMessage(jsonMessage);

                    var di      = Directory.CreateDirectory(Path.Combine(Utilities.RootPath, "Data", "Messages"));
                    var strPath = Path.Combine(di.FullName, CurrentChat.ChatID + ".txt");
                    var cm      = new Chat_Message()
                    {
                        Username    = CurrentUser.Username,
                        DisplayName = CurrentUser.DisplayName,
                        Message     = jsonMessage.Message,
                        TimeStamp   = DateTime.Now
                    };
                    File.AppendAllText(strPath, JsonConvert.SerializeObject(cm) + Environment.NewLine);
                    break;
                }

                case "Typing":
                {
                    await BroadcastMessage(jsonMessage);

                    break;
                }

                case "UpdateDisplayName":
                {
                    if (CurrentUser == null)
                    {
                        return;
                    }
                    if (jsonMessage.DisplayName.Length == 0)
                    {
                        jsonMessage.Status = "blank";
                        await SendJSON(jsonMessage);

                        return;
                    }
                    if (jsonMessage.DisplayName.Length > 20)
                    {
                        jsonMessage.Status = "too long";
                        await SendJSON(jsonMessage);

                        return;
                    }
                    CurrentUser.DisplayName = jsonMessage.DisplayName;
                    jsonMessage.Status      = "ok";
                    await SendJSON(jsonMessage);
                    await SendUserListUpdate(CurrentChat);

                    CurrentUser.Save();
                    break;
                }

                case "GetChatInfo":
                {
                    Chat chat = Chat.Load(jsonMessage.ChatID);
                    if (chat == null)
                    {
                        jsonMessage.Status = "not found";
                        await SendJSON(jsonMessage);

                        return;
                    }
                    if (chat.OwnerName != CurrentUser.Username && !chat.AdminList.Contains(CurrentUser.Username))
                    {
                        jsonMessage.Status = "unauthorized";
                        await SendJSON(jsonMessage);

                        return;
                    }
                    jsonMessage.Status = "ok";
                    jsonMessage.Chat   = chat;
                    await SendJSON(jsonMessage);

                    break;
                }

                case "AddMember":
                {
                    Chat chat = Chat.Load(jsonMessage.ChatID);
                    if (chat == null)
                    {
                        return;
                    }
                    if (chat.OwnerName != CurrentUser.Username && !chat.AdminList.Contains(CurrentUser.Username))
                    {
                        return;
                    }
                    if (!User.Exists(jsonMessage.Username))
                    {
                        jsonMessage.Status = "not found";
                    }
                    else
                    {
                        jsonMessage.Status = "ok";
                    }
                    await SendJSON(jsonMessage);

                    break;
                }

                case "AddAdmin":
                {
                    Chat chat = Chat.Load(jsonMessage.ChatID);
                    if (chat == null)
                    {
                        return;
                    }
                    if (chat.OwnerName != CurrentUser.Username && !chat.AdminList.Contains(CurrentUser.Username))
                    {
                        return;
                    }
                    if (!User.Exists(jsonMessage.Username))
                    {
                        jsonMessage.Status = "not found";
                    }
                    else
                    {
                        jsonMessage.Status = "ok";
                    }
                    await SendJSON(jsonMessage);

                    break;
                }

                case "SaveChatEdit":
                {
                    Chat chat = Chat.Load(jsonMessage.ChatID);
                    if (chat == null)
                    {
                        return;
                    }
                    if (chat.OwnerName != CurrentUser.Username && !chat.AdminList.Contains(CurrentUser.Username))
                    {
                        return;
                    }
                    string chatName = jsonMessage.ChatName;
                    if (chatName.Length > 20)
                    {
                        chatName = chatName.Substring(0, 20);
                    }
                    chat.ChatName = chatName;
                    var members = new List <string>();
                    foreach (var member in jsonMessage.Members)
                    {
                        members.Add(member.ToString());
                    }
                    chat.MemberList = members;
                    var admins = new List <string>();
                    foreach (var admin in jsonMessage.Admins)
                    {
                        admins.Add(admin.ToString());
                    }
                    chat.AdminList    = admins;
                    chat.IsMemberOnly = jsonMessage.MemberOnly;
                    chat.Save();
                    var request = new
                    {
                        Type     = "ChatUpdated",
                        ChatID   = chat.ChatID,
                        ChatName = chat.ChatName
                    };
                    var sockets = AllSockets.FindAll(sock => sock?.CurrentUser?.InvitedChats?.Contains(chat.ChatID) == true || sock?.CurrentUser?.OwnedChats?.Contains(chat.ChatID) == true || sock?.CurrentUser?.Username == chat.OwnerName);
                    foreach (var socket in sockets)
                    {
                        await socket.SendJSON(request);
                    }
                    break;
                }

                case "LoginCheckUser":
                {
                    jsonMessage.Status = User.Exists(jsonMessage.Username);
                    await SendJSON(jsonMessage);

                    break;
                }

                case "LoginExistingUser":
                {
                    if (!User.Exists(jsonMessage.Username))
                    {
                        return;
                    }
                    var user = User.Load(jsonMessage.Username);
                    if (await AuthenticateUser(user, jsonMessage) == false)
                    {
                        return;
                    }

                    var request = new
                    {
                        Type   = "LoginExistingUser",
                        Status = "ok",
                        AuthenticationToken = CurrentUser.AuthenticationTokens.Last(),
                        DisplayName         = CurrentUser.DisplayName,
                        AccountType         = CurrentUser.AccountType,
                        Username            = CurrentUser.Username,
                        Chats = GetChatList()
                    };
                    await SendJSON(request);

                    break;
                }

                case "LoginNewUser":
                {
                    foreach (var badChar in Path.GetInvalidPathChars())
                    {
                        if ((jsonMessage.Username as string).Contains(badChar))
                        {
                            jsonMessage.Status = "invalid";
                            await SendJSON(jsonMessage);

                            return;
                        }
                    }
                    if (jsonMessage.Username.Length > 20)
                    {
                        return;
                    }
                    if (User.Exists(jsonMessage.Username))
                    {
                        return;
                    }
                    if (jsonMessage.Password != jsonMessage.Confirm)
                    {
                        return;
                    }
                    var hasher = new PasswordHasher <User>();
                    CurrentUser = new User()
                    {
                        Username    = jsonMessage.Username,
                        DisplayName = Utilities.GetRandomUserName(),
                        AccountType = Utilities.Permanence.Permanent
                    };
                    CurrentUser.Password = hasher.HashPassword(CurrentUser, jsonMessage.Password);
                    CurrentUser.AuthenticationTokens.Add(Guid.NewGuid().ToString());
                    CurrentChat = new Chat()
                    {
                        ChatID       = Chat.GetNewID(),
                        OwnerName    = CurrentUser.Username,
                        ChatName     = Utilities.GetRandomChatName(),
                        ChatType     = Utilities.Permanence.Permanent,
                        IsMemberOnly = false
                    };
                    CurrentChat.Save();
                    CurrentUser.OwnedChats.Add(CurrentChat.ChatID);
                    var request = new
                    {
                        Type   = "LoginNewUser",
                        Status = "ok",
                        AuthenticationToken = CurrentUser.AuthenticationTokens.Last(),
                        DisplayName         = CurrentUser.DisplayName,
                        Username            = CurrentUser.Username,
                        AccountType         = CurrentUser.AccountType,
                        Chats = GetChatList()
                    };
                    CurrentUser.Save();
                    await SendJSON(request);

                    break;
                }

                case "GetChatHistory":
                {
                    SendChatHistory(jsonMessage.Start.ToLocalTime());
                    break;
                }

                case "DeleteChat":
                {
                    if (!Chat.Exists(jsonMessage.ChatID))
                    {
                        return;
                    }
                    Chat chat = Chat.Load(jsonMessage.ChatID);
                    if (chat.OwnerName != CurrentUser.Username && !chat.AdminList.Contains(CurrentUser.Username))
                    {
                        return;
                    }
                    if (Chat.Delete(jsonMessage.ChatID))
                    {
                        jsonMessage.Status = "ok";
                        foreach (var socket in AllSockets.FindAll(sock => sock?.CurrentChat?.ChatID == jsonMessage.ChatID))
                        {
                            await socket.SendJSON(jsonMessage);
                        }
                    }
                    else
                    {
                        jsonMessage.Status = "failed";
                        await SendJSON(jsonMessage);
                    }
                    break;
                }

                default:
                {
                    break;
                }
                }
            }
            else if (Result.MessageType == WebSocketMessageType.Binary)
            {
            }
            else if (Result.MessageType == WebSocketMessageType.Close)
            {
            }
        }