/// <summary>
 /// Updates the <see cref="Session"/> in the database
 /// </summary>
 /// <param name="session">The <see cref="Session"/> to update</param>
 public void UpdateSession(Session session) {
     _updateSession.Parameters[DatabaseUtil.MAX_PLAYERS_KEY].Value = session.MaxPlayers;
     _updateSession.Parameters[DatabaseUtil.MAX_PING_KEY].Value = session.MaxPing;
     _updateSession.Parameters[DatabaseUtil.MIN_PING_KEY].Value = session.MinPing;
     _updateSession.Parameters[DatabaseUtil.SESSION_ID_KEY].Value = session.Id;
     _updateSession.ExecuteNonQuery();
     _logger.DebugFormat("Updated session in the database with id: {0}", session.Id);
 }
        /// <summary>
        /// Gets or creates a set of <see cref="PlayerSession"/>s from the given list of <see cref="Player"/>s and the current <see cref="Session"/>.
        /// Using caching to reduce MySQL calls and speed up runtime
        /// </summary>
        /// <param name="players">List of <see cref="Player"/>s to get/create</param>
        /// <param name="session">Current <see cref="Session"/></param>
        /// <returns>A set of <see cref="PlayerSession"/> objects, from the database.</returns>
        public ISet<PlayerSession> GetOrCreatePlayerSessions(IList<Player> players, Session session) {
            ISet<PlayerSession> playerSessions = new HashSet<PlayerSession>();

            foreach (Player player in players) {
                PlayerSession playerSession = new PlayerSession();
                playerSession.Player = player;
                playerSession.Session = session;

                if (_cachedPlayerSessions.ContainsKey(player.Name)) {
                    _cachedPlayerSessions.TryGetValue(player.Name, out playerSession);
                    _logger.DebugFormat("Retrieved player session from the cache with ID: {0}", playerSession.Id);
                } else {
                    _getPlayerSession.Parameters[DatabaseUtil.NAME_KEY].Value = player.Name;
                    _getPlayerSession.Parameters[DatabaseUtil.SESSION_ID_KEY].Value = session.Id;

                    MySqlDataReader getPlayerResult = _getPlayerSession.ExecuteReader();

                    if (getPlayerResult.HasRows) {
                        getPlayerResult.Read();
                        playerSession.Player.Id = getPlayerResult.GetInt32(0);

                        if (getPlayerResult.GetBoolean(1) != playerSession.Player.HasClanTag) {
                            playerSession.Player.Updated = true;
                        }

                        if (getPlayerResult.IsDBNull(2)) {
                            getPlayerResult.Close();
                            CreatePlayerSession(playerSession);
                        } else {
                            playerSession.Id = getPlayerResult.GetInt32(2);
                            playerSession.Length = getPlayerResult.GetInt32(3);
                            playerSession.Played = getPlayerResult.GetBoolean(4);
                            _logger.DebugFormat("Retrieved player session from the database with ID: {0}", playerSession.Id);

                            getPlayerResult.Close();
                        }
                    } else {
                        getPlayerResult.Close();
                        _addPlayer.Parameters[DatabaseUtil.NAME_KEY].Value = player.Name;
                        _addPlayer.Parameters[DatabaseUtil.HAS_CLAN_TAG_KEY].Value = player.HasClanTag;
                        _addPlayer.ExecuteNonQuery();

                        playerSession.Player.Id = GetLastInsertedId();

                        CreatePlayerSession(playerSession);                   
                    }
                    _cachedPlayerSessions.Add(player.Name, playerSession);
                }
                playerSessions.Add(playerSession);
            }

            return playerSessions;
        }
        /// <summary>
        /// Inserts a <see cref="Session"/> object into the database
        /// </summary>
        /// <param name="session"><see cref="Session"/> to create in the database</param>
        /// <returns>The <see cref="Session"/> with updated values from the database</returns>
        public Session CreateSession(Session session) {
            session.Date = DateTime.Now;

            _addSession.Parameters[DatabaseUtil.DATE_KEY].Value = session.Date;
            _addSession.Parameters[DatabaseUtil.MAX_PLAYERS_KEY].Value = session.MaxPlayers;
            _addSession.Parameters[DatabaseUtil.VERSION_KEY].Value = session.Version;
            _addSession.Parameters[DatabaseUtil.HOST_NAME_KEY].Value = session.HostName;
            _addSession.Parameters[DatabaseUtil.MIN_PING_KEY].Value = session.MinPing;
            _addSession.Parameters[DatabaseUtil.MAX_PING_KEY].Value = session.MaxPing;
            _addSession.ExecuteNonQuery();

            session.Id = GetLastInsertedId();
            _logger.DebugFormat("Created session in the database with id: {0}", session.Id);

            return session;
        }
        /// <summary>
        /// Helper method to update <see cref="Mission"/> data in the database
        /// </summary>
        /// <param name="missionDAO">DAO for <see cref="Mission"/>s</param>
        /// <param name="session">The current game <see cref="Session"/></param>
        /// <param name="serverInfo">The current <see cref="ServerInfo"/></param>
        /// <param name="missionCount">The number of missions played</param>
        /// <returns>The current <see cref="MissionSession"/></returns>
        private MissionSession UpdateMissionData(MissionDAO missionDAO, Session session, ServerInfo serverInfo, ref int missionCount) {
            MissionSession missionSession = missionDAO.GetOrCreateMissionSession(serverInfo.MapName, serverInfo.Mission, session);

            missionSession.Updated = true;
            missionSession.Length += (Settings.Default.pollRate / 1000);
            if (missionSession.Played == false && CheckPlayedThreshold(missionSession.Length)) {
                missionSession.Played = true;
                missionCount++;
            }

            missionDAO.UpdateMissionSession(missionSession);

            return missionSession;
        }
        /// <summary>
        /// Helper method to update <see cref="Player"/> data in the database
        /// </summary>
        /// <param name="playerDAO">DAO for <see cref="Player"/>s</param>
        /// <param name="session">The current game <see cref="Session"/></param>
        /// <param name="serverInfo">The current <see cref="ServerInfo"/></param>
        /// <param name="missionSession">The current <see cref="MissionSession"/></param>
        /// <returns>The current set of <see cref="PlayerSession"/>s</returns>
        private ISet<PlayerSession> UpdatePlayerData(PlayerDAO playerDAO, Session session, ServerInfo serverInfo, MissionSession missionSession) {
            ISet<PlayerSession> playerSessions = playerDAO.GetOrCreatePlayerSessions(serverInfo.Players, session);

            foreach (PlayerSession playerSession in playerSessions) {
                playerSession.Updated = true;
                playerSession.Length += (Settings.Default.pollRate / 1000);
                if (playerSession.Played == false && CheckPlayedThreshold(playerSession.Length)) {
                    playerSession.Played = true;
                }
            }

            playerDAO.UpdatePlayerSessions(playerSessions);
            return playerSessions;
        }
        /// <summary>
        /// Helper method to update <see cref="Session"/> data in the database
        /// </summary>
        /// <param name="sessionDAO">DAO for <see cref="Session"/>s</param>
        /// <param name="session">The current game <see cref="Session"/></param>
        /// <param name="serverInfo">The current <see cref="ServerInfo"/></param>
        private void UpdateSessionData(SessionDAO sessionDAO, Session session, ServerInfo serverInfo) {
            bool updateSession = false;

            if (session.MaxPing < serverInfo.Ping) {
                session.MaxPing = serverInfo.Ping;
                updateSession = true;
            } else if (session.MinPing > serverInfo.Ping) {
                session.MinPing = serverInfo.Ping;
                updateSession = true;
            }

            if (session.MaxPlayers < serverInfo.Players.Count) {
                session.MaxPlayers = serverInfo.Players.Count;
                updateSession = true;
            }

            if (updateSession) {
                sessionDAO.UpdateSession(session);
            }
        }
 /// <summary>
 /// Helper method to update the session info
 /// </summary>
 /// <param name="serverInfoService">service to get info from an A3 server</param>
 /// <param name="sessionDAO">DAO for <see cref="Session"/>s</param>
 /// <param name="playerDAO">DAO for <see cref="Player"/>s</param>
 /// <param name="missionDAO">DAO for <see cref="Mission"/>s</param>
 /// <param name="pstmsDAO">DAO for <see cref="PlayerSessionToMissionSession"/>s</param>
 /// <param name="host">A3 server host</param>
 /// <param name="port">A3 server port</param>
 /// <param name="session">The current game <see cref="Session"/></param>
 /// <param name="missionCount">The number of missions played</param>
 /// <param name="inGame">Boolean to check if the server is currently in game</param>
 /// <returns>The current mission session</returns>
 private Session UpdateInfo(ServerInfoService serverInfoService, SessionDAO sessionDAO, PlayerDAO playerDAO, MissionDAO missionDAO, PlayerSessionToMissionSessionDAO pstmsDAO,
                            string host, int port, Session session, ref int missionCount, ref bool inGame) {
     ServerInfo serverInfo = serverInfoService.GetServerInfo(host, port);
     inGame = CheckServerRunningState(serverInfo.ServerState);
     if (inGame) {
         UpdateSessionData(sessionDAO, session, serverInfo);
         MissionSession missionSession = UpdateMissionData(missionDAO, session, serverInfo, ref missionCount);
         ISet<PlayerSession> playerSessions = UpdatePlayerData(playerDAO, session, serverInfo, missionSession);
         UpdatePTSTMTSData(pstmsDAO, missionSession, playerSessions);
     }
     return session;
 }
        /// <summary>
        /// Helper method to create a new session
        /// </summary>
        /// <param name="serverInfoService">service to get info from an A3 server</param>
        /// <param name="sessionDAO">DAO for sessions</param>
        /// <param name="host">A3 server host</param>
        /// <param name="port">A3 server port</param>
        /// <param name="inGame">Boolean to check if the server is currently in game</param>
        /// <returns>The new session</returns>
        private Session SetUpSession(ServerInfoService serverInfoService, SessionDAO sessionDAO, string host, int port, ref bool inGame) {
            Session returnSession = null;

            // initial info grab
            ServerInfo serverInfo = serverInfoService.GetServerInfo(host, port);
            inGame = CheckServerRunningState(serverInfo.ServerState);

            if (inGame) {
                // create a session
                Session session = new Session();
                session.HostName = serverInfo.HostName;
                session.Version = serverInfo.GameVersion;
                session.MaxPing = serverInfo.Ping;
                session.MinPing = serverInfo.Ping;
                session.MaxPlayers = serverInfo.NumPlayers;
                session = sessionDAO.CreateSession(session);

                returnSession = session;
            }

            return returnSession;
        }