void aiWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            AIAttentionRequiredResult aiGameAttentionRequired = (AIAttentionRequiredResult)e.Argument;
            GameState state = TicTacToeHost.Instance.GetGameState(aiGameAttentionRequired.GameId, aiGameAttentionRequired.PlayerId);
            int[,] aiBoard = new int[3, 3];
            for (int x = 0; x < 3; x++)
            {
                for (int y = 0; y < 3; y++)
                {
                    aiBoard[x, y] = state.GameBoard[x][y] == null ? 0 : state.GameBoard[x][y].Value;
                }
            }
            GameBoard ai = new GameBoard(aiBoard);
            Move aiMove = ai.GetMove(1);
            Games.Move gameMove = new Games.Move();
            gameMove.GameId = aiGameAttentionRequired.GameId;
            gameMove.PlayerId = aiGameAttentionRequired.PlayerId;
            gameMove.OriginX = aiMove.OriginX;
            gameMove.OriginY = aiMove.OriginY;
            gameMove.X = aiMove.X;
            gameMove.Y = aiMove.Y;

            var moveReuslt = TicTacToeHost.Instance.Move(gameMove);
            if (moveReuslt != MoveResult.Valid)
            {
                //using(IGameDataService dataService = new GameDataService())
                //{
                //    Match match = dataService.GetMatch(null, aiGameAttentionRequired.GameId);
                //    Player tttdPlayer = dataService.GetPlayer(aiGameAttentionRequired.PlayerId);
                //    CentralServerSession session = dataService.GetCentralServerSession(null, null, aiGameAttentionRequired.GameId);

                //    dataService.EndGame(aiGameAttentionRequired.GameId, match.PlayerOneId == aiGameAttentionRequired.PlayerId ? match.PlayerTwoId : match.PlayerOneId);

                //    MoveRequest challengeRequest = new MoveRequest();
                //    challengeRequest.GameId = session.CentralServerGameId.Value;
                //    challengeRequest.PlayerName = tttdPlayer.PlayerName;
                //    challengeRequest.X = 0;
                //    challengeRequest.Y = 0;
                //    challengeRequest.Flags = CentralServerCommunicationChannel.GetStatus(StatusFlag.AcceptLoss);
                //    CentralServerCommunicationChannel.Instance.PostMove(challengeRequest, match.CurrentGameId.Value, match.MatchId);
                //}
            }

            using (IGameDataService gameDataService = new GameDataService())
            {
                AIGame aiGame = gameDataService.GetAIGame(aiGameAttentionRequired.GameId, aiGameAttentionRequired.PlayerId);
                gameDataService.Attach(aiGame);
                aiGame.EvaluatingMove = false;
                gameDataService.Save();
            }
        }
        static void ChallengePlayerCompleted(string data, int matchId)
        {
            var response = JsonSerializer.DeseriaizeFromJSON<ChallengeResponse>(data);
            if (string.IsNullOrEmpty(response.Error))
            {
                Match match;
                CentralServerSession session;
                using (IGameDataService dataService = new GameDataService())
                {
                    match = dataService.GetMatch(matchId, null);
                    session = dataService.GetCentralServerSession(null, null, match.CurrentGameId.Value);

                    dataService.Attach(session);
                    session.CentralServerGameId = response.GameId;
                    dataService.Save();

                    TicTacToeHost.Instance.AcceptChallenge(match.PlayerTwoId, match.MatchId);

                    if (response.YourTurn)
                    {
                        dataService.SetPlayerTurn(match.CurrentGameId.Value, match.PlayerOneId);
                        dataService.Save();
                    }
                    else
                    {
                        dataService.SetPlayerTurn(match.CurrentGameId.Value, match.PlayerTwoId);
                        dataService.Save();
                        TicTacToeHost.Instance.Move(new Move() { GameId = match.CurrentGameId.Value, PlayerId = match.PlayerTwoId, X = response.X, Y = response.Y }, false);
                    }
                }
            }
        }
        ///// <summary>
        ///// Set up a new game between two players. Will return the id of the created game.
        ///// </summary>
        ///// <param name="config">The parameters necessary to set up the game.</param>
        ///// <returns></returns>
        //public int ConfigureGame(GameConfiguration config)
        //{
        //    return ConfigureGame(config, null, true, true);
        //}
        public int ConfigureGame(int matchId)
        {
            using (IGameDataService gameDataService = new GameDataService())
            {
                //Create a game, as well as a match in case the players play multiple games in a row.
                Models.Match match = gameDataService.GetMatch(matchId, null);

                if (match == null)
                    throw new InvalidOperationException("A match is required for game play.");

                Models.Player playerOne = gameDataService.GetPlayer(match.PlayerOneId);
                Models.Player playerTwo = gameDataService.GetPlayer(match.PlayerTwoId);

                Models.Game game = gameDataService.CreateGame(playerOne, playerTwo, match);
                GameConfiguration config = GameConfigCache.Instance.GetConfig(matchId);

                //Make an entry in the table for AI to track the game.
                Models.AIGame aiPlayerOne;
                if (config.PlayerOne.PlayerType == PlayerType.AI)
                    aiPlayerOne = gameDataService.CreateAIGame(playerOne, game, match);

                //We only want to be responsible for managing local AIs.
                //If it's networked, don't record it.
                Models.AIGame aiPlayerTwo;
                if (config.PlayerTwo.PlayerType == PlayerType.AI && config.GameType != GameType.Network)
                    aiPlayerTwo = gameDataService.CreateAIGame(playerTwo, game, match);

                gameDataService.Attach(match);
                match.CurrentGameId = game.GameId;
                match.StateDate = game.StateDate;

                gameDataService.Save();

                return game.GameId;
            }
        }
        private void UpdateChallengeState(int playerId, int matchId, bool? state)
        {
            using (IGameDataService gameDataService = new GameDataService())
            {
                Match match = gameDataService.GetMatch(matchId, null);
                GameConfiguration config = GameConfigCache.Instance.GetConfig(matchId);

                if (match.EndDate == null)
                {
                    gameDataService.Attach(match);

                    bool challengeStateChange = false;
                    if (match.PlayerOneId == playerId && match.PlayerOneAccepted != state)
                    {
                        match.PlayerOneAccepted = state;
                        challengeStateChange = true;
                    }
                    else if (match.PlayerTwoId == playerId && match.PlayerTwoAccepted != state)
                    {
                        match.PlayerTwoAccepted = state;
                        challengeStateChange = true;
                    }

                    if (playerId == match.PlayerOneId || playerId == match.PlayerTwoId && challengeStateChange)
                    {
                        match.StateDate = DateTime.Now;
                        if (match.PlayerOneAccepted == false && match.PlayerTwoAccepted == false)
                        {
                            match.EndDate = match.StateDate;
                        }
                        else if (match.PlayerOneAccepted == true
                            && match.PlayerTwoAccepted == true
                            && config.GameType != GameType.Network)
                        {
                            gameDataService.SetPlayerTurn(match.CurrentGameId.Value, match.PlayerOneId);
                        }
                    }

                    gameDataService.Save();
                }
            }
        }
        public void CancelChallenge(int matchId, string reason)
        {
            using (IGameDataService gameDataService = new GameDataService())
            {
                Match match = gameDataService.GetMatch(matchId, null);
                gameDataService.Attach(match);
                match.EndDate = DateTime.Now;
                match.StateDate = match.EndDate.Value;

                List<Game> matchGames = gameDataService.Repository.GetGames().Where(game => game.MatchId == matchId).ToList();
                foreach (var game in matchGames)
                {
                    if (game.EndDate == null)
                    {
                        gameDataService.Attach(game);
                        game.EndDate = match.EndDate;
                        game.StateDate = match.EndDate.Value;
                    }
                }

                gameDataService.Save();
            }
            Logger.Instance.Log("MatchCancelled", string.Format("match:{0}", matchId), reason);
        }