public static void CreateChannel(string channelName, string userNickname, string password)
        {
            ValidateChannelName(channelName);
            ValidateNickname(userNickname);
            using (ChatContext context = new ChatContext())
            {
                var nameToLower = channelName.ToLower();

                var dbChannel = context.Channels.FirstOrDefault(c => c.Name.ToLower() == nameToLower);

                if (dbChannel != null)
                {
                    if (dbChannel.Name.ToLower() == nameToLower)
                    {
                        throw new ServerErrorException("Channel name already exists", "ERR_DUP_CHNAME");
                    }
                }

                dbChannel = new Channel()
                {
                    Name = nameToLower,
                    Password = password
                };

                var dbUser = context.Users.FirstOrDefault(u => u.Nickname.ToLower() == userNickname.ToLower());
                dbChannel.Users.Add(dbUser);

                context.Channels.Add(dbChannel);
                context.SaveChanges();
            }
        }
 public static void CreateMessage(Message message)
 {
     using (ChatContext context = new ChatContext())
     {
         context.Messages.Add(message);
         context.SaveChanges();
     }
 }
 static void Main(string[] args)
 {
     ChatContext context = new ChatContext();
     context.Users.Add(new User()
         {
             Username = "******",
             AuthCode = "asdasdads",
             Nickname = "Pesho p",
         });
     context.SaveChanges();
 }
        public static void AddMessage(string channelName, string senderNickname, string messageText)
        {
            ValidateChannelName(channelName);
            ValidateNickname(senderNickname);
            using (ChatContext context = new ChatContext())
            {
                Message currentMsg = new Message()
                {
                    Author = senderNickname,
                    Content = messageText,
                    DateTime = DateTime.Now,
                };

                var dbChannel = context.Channels.FirstOrDefault(c => c.Name.ToLower() == channelName.ToLower());
                dbChannel.History.Add(currentMsg);

                context.SaveChanges();
            }
        }
        public static void ExitChannel(string channelName, string userNickname)
        {
            ValidateChannelName(channelName);
            ValidateNickname(userNickname);
            using (var context = new ChatContext())
            {
                var nameToLower = channelName.ToLower();

                var dbChannel = context.Channels.FirstOrDefault(c => c.Name.ToLower() == nameToLower);
                var dbUser = context.Users.FirstOrDefault(u => u.Nickname.ToLower() == userNickname.ToLower());

                dbChannel.Users.Remove(dbUser);

                if (dbChannel.Users.Count == 0)
                {
                    context.Messages.RemoveRange(dbChannel.History);
                    context.Channels.Remove(dbChannel);
                }

                context.SaveChanges();
            }
        }
        public static void JoinChannel(string channelName, string userNickname, string password)
        {
            ValidateChannelName(channelName);
            ValidateNickname(userNickname);
            using (ChatContext context = new ChatContext())
            {
                var nameToLower = channelName.ToLower();

                var dbChannel = context.Channels.FirstOrDefault(c => c.Name.ToLower() == nameToLower);

                if (dbChannel == null)
                {
                    if (dbChannel.Name.ToLower() == nameToLower)
                    {
                        throw new ServerErrorException("Channel name does not exists.", "ERR_DUP_CHNAME"); //TODO: Fix Error code
                    }
                }

                if (dbChannel.Password != password)
                {
                    throw new ServerErrorException("Password incorrect.", "INV_USR_AUTH"); //TODO: Fix Error code
                }

                var dbUser = context.Users.FirstOrDefault(u => u.Nickname.ToLower() == userNickname.ToLower());

                var alreadyJoinedChannel = dbUser.Channels.FirstOrDefault(ch => ch.Name.ToLower() == channelName.ToLower());
                if (alreadyJoinedChannel != null)
                {
                    throw new ServerErrorException("Already joined channel.", "ERR_JOINED_CHANNEL"); //TODO: Add error code
                }

                dbChannel.Users.Add(dbUser);

                context.SaveChanges();
            }
        }
        public static ChannelHasPasswordModel GetChannelByName(string name)
        {
            using (ChatContext context = new ChatContext())
            {
                var channel = context.Channels.FirstOrDefault(c => c.Name.ToLower() == name.ToLower());
                var chanelHasPassword = new ChannelHasPasswordModel()
                {
                    Name = channel.Name,
                    HasPassword = !String.IsNullOrEmpty(channel.Password)
                };

                return chanelHasPassword;
            }
        }
        public static IEnumerable<UserModel> GetUsers(string channelName)
        {
            ValidateChannelName(channelName);
            using (ChatContext context = new ChatContext())
            {
                var channel = context.Channels.FirstOrDefault(c => c.Name.ToLower() == channelName.ToLower());

                var users = channel.Users.Select(new Func<User, UserModel>(x => new UserModel()
                {
                    Nickname = x.Nickname
                })).ToList();

                return users;
            }
        }
        public static IEnumerable<MessageModel> GetHistory(string channelName)
        {
            ValidateChannelName(channelName);
            using (ChatContext context = new ChatContext())
            {
                var dbChannel = context.Channels.FirstOrDefault(c => c.Name.ToLower() == channelName.ToLower());

                if (dbChannel == null)
                {
                    throw new ServerErrorException(); //TODO: error messages
                }

                var history = dbChannel.History.OrderBy(x => x.DateTime).ToList();

                var historyModel = history.OrderBy(x => x.DateTime).Select(new Func<Message, MessageModel>(x => new MessageModel()
                {
                    Author = x.Author,
                    Content = x.Content,
                    DateTime = x.DateTime,
                    Channel = x.Channel.Name,
                    MessageId = x.MessageId
                })).ToList();

                return historyModel;
            }
        }
        public static IEnumerable<ChannelModel> GetChannels()
        {
            using (ChatContext context = new ChatContext())
            {
                var channels = context.Channels.Select(x => new ChannelModel()
                {
                    Name = x.Name,
                    Users = x.Users.Select(u => u.Nickname)
                }).ToList();

                return channels;
            }
        }
        public static IEnumerable<ChannelModel> GetChannels()
        {
            using (ChatContext context = new ChatContext())
            {
                var channels = context.Channels.Select(new Func<Channel, ChannelModel>(x => new ChannelModel()
                {
                    Name = x.Name
                })).ToList();

                return channels;
            }
        }
        /* public members */

        public static void CreateUser(string username, string nickname, string authCode)
        {
            ValidateUsername(username);
            ValidateNickname(nickname);
            ValidateAuthCode(authCode);
            using (ChatContext context = new ChatContext())
            {
                var usernameToLower = username.ToLower();
                var nicknameToLower = nickname.ToLower();

                var dbUser = context.Users.FirstOrDefault(u => u.Username.ToLower() == usernameToLower || u.Nickname.ToLower() == nicknameToLower);

                if (dbUser != null)
                {
                    if (dbUser.Username.ToLower() == usernameToLower)
                    {
                        throw new ServerErrorException("Username already exists", "ERR_DUP_USR");
                    }
                    else
                    {
                        throw new ServerErrorException("Nickname already exists", "ERR_DUP_NICK");
                    }
                }

                dbUser = new User()
                {
                    Username = usernameToLower,
                    Nickname = nickname,
                    AuthCode = authCode
                };
                context.Users.Add(dbUser);
                context.SaveChanges();
            }

        }
 public static IEnumerable<User> GetAllUsers()
 {
     var context = new ChatContext();
     using (context)
     {
         var users =
             (from user in context.Users
              select new User()
              {
                  Nickname = user.Nickname,
                 });
         return users.ToList();
     }
 }
 public static void LogoutUser(string sessionKey)
 {
     ValidateSessionKey(sessionKey);
     var context = new ChatContext();
     using (context)
     {
         var user = context.Users.FirstOrDefault(u => u.SessionKey == sessionKey);
         if (user == null)
         {
             throw new ServerErrorException("Invalid user authentication", "INV_USR_AUTH");
         }
         user.SessionKey = null;
         context.SaveChanges();
     }
 }
 public static int LoginUser(string sessionKey)
 {
     ValidateSessionKey(sessionKey);
     var context = new ChatContext();
     using (context)
     {
         var user = context.Users.FirstOrDefault(u => u.SessionKey == sessionKey);
         if (user == null)
         {
             throw new ServerErrorException("Invalid user authentication", "INV_USR_AUTH");
         }
         return user.UserId;
     }
 }
        public static string LoginUser(string username, string authCode, out string nickname)
        {
            ValidateUsername(username);
            ValidateAuthCode(authCode);
            var context = new ChatContext();
            using (context)
            {
                var usernameToLower = username.ToLower();
                var user = context.Users.FirstOrDefault(u => u.Username.ToLower() == usernameToLower && u.AuthCode == authCode);
                if (user == null)
                {
                    throw new ServerErrorException("Invalid user authentication", "INV_USR_AUTH");
                }

                var sessionKey = GenerateSessionKey(user.UserId);
                user.SessionKey = sessionKey;
                nickname = user.Nickname;
                context.SaveChanges();
                return sessionKey;
            }
        }