public static IEnumerable<MessageModel> GetAllMessages(int userId)
        {
            var context = new BattleGameEntities();
            using (context)
            {
                var user = GetUser(userId, context);
                var messages = user.UserMessages;

                var messageModels =
                                   (from msg in messages
                                    select new MessageModel()
                                    {
                                        State = msg.MessageState.State,
                                        Text = msg.Text,
                                        GameId = (int)msg.Game.Id,
                                        GameTitle = msg.Game.Title,
                                        Type = msg.UserMessagesType.Type
                                    }).ToList();
                var readMessageState = context.MessageStates.First(st => st.State == "read");
                foreach (var msg in user.UserMessages)
                {
                    msg.MessageState = readMessageState;
                }
                context.SaveChanges();
                return messageModels;
            }
        }
        /* public members */
        public static void CreateGame(int userId, string title, string password)
        {
            ValidateGameTitle(title);
            if (password != null)
            {
                ValidateGamePassword(password);
            }

            var context = new BattleGameEntities();
            using (context)
            {
                var user = GetUser(userId, context);

                var game = new Game()
                {
                    Title = title,
                    Password = password,
                    Status = context.Statuses.First(st => st.Value == GameStatusOpen),
                    RedUser = user
                };
                context.Games.Add(game);

                context.SaveChanges();
            }
        }
        /* public methods */
        public static void CreateUser(string username, string nickname, string authCode)
        {
            ValidateUsername(username);
            ValidateNickname(nickname);
            ValidateAuthCode(authCode);
            using (BattleGameEntities context = new BattleGameEntities())
            {
                var usernameToLower = username.ToLower();
                var nicknameToLower = nickname.ToLower();

                var dbUser = context.Users.FirstOrDefault(u => u.Username == 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 void JoinGame(int userId, int gameId, string password)
        {
            if (password != null)
            {
                ValidateGamePassword(password);
            }
            var context = new BattleGameEntities();
            using (context)
            {
                var user = GetUser(userId, context);

                var game = context.Games.FirstOrDefault(g => g.Id == gameId);
                if (game == null)
                {
                    throw new ServerErrorException("No such game", "ERR_INV_GAME");
                }

                ValidateOpenGameStatus(game, context);

                if (game.Password != null && game.Password != password)
                {
                    throw new ServerErrorException("Invalid game password", "INV_GAME_PASS");
                }

                game.BlueUser = user;

                string messageText = string.Format("{0} just joined your game {1}", game.BlueUser.Nickname, game.Title);
                UserMessagesType gameJoinedUserMessageType = context.UserMessagesTypes.First(mt => mt.Type == UserMessageTypeGameJoined);
                SendMessage(messageText, game.RedUser, game, gameJoinedUserMessageType, context);

                var fullGameStatus = context.Statuses.First(st => st.Value == GameStatusFull);
                game.Status = fullGameStatus;

                context.SaveChanges();
            }
        }
        public static void StartGame(int gameId)
        {
            var context = new BattleGameEntities();
            using (context)
            {
                var game = GetGame(gameId, context);
                if (game.Status.Value != GameStatusFull)
                {
                    throw new ServerErrorException("Nobody has joined this game", "INV_GAME_STATE");
                }

                UnitType warriorType = context.UnitTypes.First(type => type.Value == WarriorType);
                UnitType rangerType = context.UnitTypes.First(type => type.Value == RangerType);
                var redUnits = GenerateUnits(RedWarriorsPositionX, RedRangerPositionX, warriorType, rangerType);

                var attackMode = context.Modes.First(m => m.Value == UnitAttackMode);

                foreach (var unit in redUnits)
                {
                    unit.Mode = attackMode;
                    unit.User = game.RedUser;
                    game.Units.Add(unit);
                }

                var blueUnits = GenerateUnits(BlueWarriorsPositionX, BlueRangerPositionX, warriorType, rangerType);
                foreach (var unit in blueUnits)
                {
                    unit.Mode = attackMode;
                    unit.User = game.BlueUser;
                    game.Units.Add(unit);
                }

                game.Status = context.Statuses.First(st => st.Value == GameStatusInProgress);

                game.Turn = 0;
                var userInTurn = (rand.Next() % 2 == 0) ? game.RedUser : game.BlueUser;
                game.UserInTurn = userInTurn.Id;

                var gameStartedMessageText = string.Format("{0} just started game {1}", game.RedUser.Nickname, game.Title);
                var gameStartedMessageType = context.UserMessagesTypes.First(mt => mt.Type == UserMessageTypeGameStarted);
                SendMessage(gameStartedMessageText, game.BlueUser, game, gameStartedMessageType, context);

                var gameMoveMessageText = string.Format("It is your turn in game {0}", game.Title);
                var gameMoveMessageType = context.UserMessagesTypes.First(mt => mt.Type == UserMessageTypeGameMove);
                SendMessage(gameMoveMessageText, userInTurn, game, gameMoveMessageType, context);

                context.SaveChanges();
            }
        }
 public static void LogoutUser(string sessionKey)
 {
     ValidateSessionKey(sessionKey);
     var context = new BattleGameEntities();
     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 string LoginUser(string username, string authCode, out string nickname)
        {
            ValidateUsername(username);
            ValidateAuthCode(authCode);
            var context = new BattleGameEntities();
            using (context)
            {
                var usernameToLower = username.ToLower();
                var user = context.Users.FirstOrDefault(u => u.Username == usernameToLower && u.AuthCode == authCode);
                if (user == null)
                {
                    throw new ServerErrorException("Invalid username or password", "ERR_INV_USR");
                }

                var sessionKey = GenerateSessionKey((int)user.Id);
                user.SessionKey = sessionKey;
                nickname = user.Nickname;
                context.SaveChanges();
                return sessionKey;
            }
        }
        /* public members */

        public static void PerformMove(int userId, int gameId, int unitId, long toX, long toY)
        {
            var context = new BattleGameEntities();
            using (context)
            {
                Game game = GetGame(gameId, context);
                ValidateGameInProgressStatus(game, context);

                User user = GetUser(userId, context);
                Unit unit = GetUnit(unitId, context);

                ValidateUserUnitInGame(user, unit, game);

                ValidateUnitMovePosition(game, unit, toX, toY);

                unit.Mode = context.Modes.First(m => m.Value == UnitModeAttack);
                unit.PositionX = toX;
                unit.PositionY = toY;

                var otherUser = (game.RedUser == user) ? game.BlueUser : game.RedUser;

                game.Turn++;
                game.UserInTurn = otherUser.Id;

                var messageText = string.Format(GameMoveMessageText, user.Nickname, game.Title);
                var gameMoveUserMessagesType = context.UserMessagesTypes.First(mt => mt.Type == GameMoveMessageType);
                SendMessage(messageText, otherUser, game, gameMoveUserMessagesType, context);
                context.SaveChanges();
            }
        }
        public static void PerformDefend(int userId, int gameId, int unitId)
        {
            var context = new BattleGameEntities();

            using (context)
            {
                var game = GetGame(gameId, context);
                ValidateGameInProgressStatus(game, context);

                var user = GetUser(userId, context);
                var unit = GetUnit(unitId, context);
                ValidateUserUnitInGame(user, unit, game);

                unit.Mode = context.Modes.First(m => m.Value == UnitModeDefend);
                
                var otherUser = (game.RedUser == user) ? game.BlueUser : game.RedUser;
                game.Turn++;
                game.UserInTurn = otherUser.Id;

                context.SaveChanges();
            }
        }
        public static void PerformAttack(int userId, int gameId, int unitId, long toX, long toY)
        {
            var context = new BattleGameEntities();
            using (context)
            {
                var game = GetGame(gameId, context);
                ValidateGameInProgressStatus(game, context);

                User user = GetUser(userId, context);
                Unit unit = GetUnit(unitId, context);

                ValidateUserUnitInGame(user, unit, game);

                ValidateUnitAttackPosition(game, unit, user, toX, toY);

                Unit attackedUnit = GetAttackedUnit(user, game, toX, toY);
                var attackedUnitArmor = attackedUnit.Armor;
                if (attackedUnit.Mode.Value == UnitModeDefend)
                {
                    attackedUnitArmor *= 2;
                }

                unit.Mode = context.Modes.First(m => m.Value == UnitModeAttack);
                var dmgTaken = unit.Attack - attackedUnitArmor;
                if (dmgTaken > 0)
                {
                    attackedUnit.HitPoints -= dmgTaken;
                }
                context.SaveChanges();

                var otherUser = (game.RedUser == user) ? game.BlueUser : game.RedUser;

                game.Turn++;

                if (game.Units.Any(u => u.User == otherUser && u.HitPoints > 0))
                {
                    game.UserInTurn = otherUser.Id;
                    var messageText = string.Format(GameMoveMessageText, user.Nickname, game.Title);
                    var gameMoveUserMessagesType = context.UserMessagesTypes.First(mt => mt.Type == GameMoveMessageType);
                    SendMessage(messageText, otherUser, game, gameMoveUserMessagesType, context);
                }
                else
                {
                    var finishedGameStatus = context.Statuses.First(st => st.Value == GameStatusFinished);
                    game.Status = finishedGameStatus;

                    var finishedGameMessageType = context.UserMessagesTypes.First(umt => umt.Type == UserMessageTypeGameFinished);

                    var messageTextWinner = string.Format("You won in game {0} against {1} in {2} moves!", game.Title, otherUser.Nickname, game.Turn);
                    SendMessage(messageTextWinner, user, game, finishedGameMessageType, context);

                    var messageTextLoser = string.Format("You were beaten in game {0} by {1}", game.Title, user.Nickname);
                    SendMessage(messageTextLoser, otherUser, game, finishedGameMessageType, context);

                    var score = game.Units.Where(u => u.User == user && u.HitPoints > 0).Sum(u => u.HitPoints);
                    user.Scores.Add(new Score()
                    {
                        Value = score
                    });
                }

                context.SaveChanges();
            }
        }