// TODO: Currently there is no limit in the raise amount as long as it is positive number
        public PlayerAction DoPlayerAction(PlayerAction action, int maxMoneyPerPlayer)
        {
            if (action.Type == PlayerActionType.Raise)
            {
                this.CallTo(maxMoneyPerPlayer);

                if (this.Money <= 0)
                {
                    return PlayerAction.CheckOrCall();
                }

                if (this.Money > action.Money)
                {
                    this.PlaceMoney(action.Money);
                }
                else
                {
                    // All-in
                    action.Money = this.Money;
                    this.PlaceMoney(action.Money);
                }
            }
            else if (action.Type == PlayerActionType.CheckCall)
            {
                this.CallTo(maxMoneyPerPlayer);
            }
            else //// PlayerActionType.Fold
            {
                this.InHand = false;
                this.ShouldPlayInRound = false;
            }

            return action;
        }
        public static IList<Card[]> PredictEnemyCardsPreFlop(Card firstCard, Card secondCard, PlayerAction firstEnemyPreFlopAction)
        {
            var ourHandsCards = new Card[] { firstCard, secondCard }; // ours + comunity cards

            var remainingCards = FullDeck.ToList();

            foreach (var card in ourHandsCards)
            {
                remainingCards.Remove(card);
            }

            IEnumerable<Card[]> oponentCardsVariants = CardsCombinations.CombinationsNoRepetitionsIterative(remainingCards, PlayerCardsCount);

            List<Card[]> opponentLikelyCardsPredictions = new List<Card[]>();

            foreach (var oponentCardsVariant in oponentCardsVariants)
            {
                var enemyOdds = HandStrengthValuation.PreFlopOdsLookupTable(oponentCardsVariant[0],
                    oponentCardsVariant[1]);

                if (firstEnemyPreFlopAction.Money > 0 && enemyOdds > MinBetThreshold) // .6
                {
                    opponentLikelyCardsPredictions.Add(oponentCardsVariant);
                }
                else if (firstEnemyPreFlopAction.Money == 0 && enemyOdds <= MaxCallThreshold) // .65
                {
                    opponentLikelyCardsPredictions.Add(oponentCardsVariant);
                }
            }

            return opponentLikelyCardsPredictions;
        }
        internal void ProcessCurrentRound(GetTurnContext context, Card firstCard, Card secondCard, IReadOnlyCollection<Card> communityCards)
        {
            float[] probabilityOfAllHands = new float[9];

            if (context.RoundType == GameRoundType.PreFlop)
            {
                var firstHandProbability = initialHandStrength.EvaluateHand(firstCard, secondCard);

                this.Action = decisionMaker.DesideByChance(firstHandProbability, context);
            }
            else
            {
                this.handIndex = bestHandStrenght.Evaluate(firstCard, secondCard, communityCards);
                probabilityOfAllHands = probabilityEvaluator.Evaluate(firstCard, secondCard, communityCards, context.RoundType);

                this.Action = decisionMaker.Deside(probabilityOfAllHands, context, handIndex);
            }
        }
        private PlayerAction DoPlayerAction(InternalPlayer player, PlayerAction action, int maxMoneyPerPlayer)
        {
            if (action.Type == PlayerActionType.Raise)
            {
                player.Call(maxMoneyPerPlayer);

                if (player.Money <= 0)
                {
                    return PlayerAction.CheckOrCall();
                }

                foreach (var playerToUpdate in this.allPlayers)
                {
                    playerToUpdate.ShouldPlayInRound = true;
                }

                // TODO: Min raise?
                if (player.Money > action.Money)
                {
                    player.PlaceMoney(action.Money);
                }
                else
                {
                    // All-in
                    action.Money = player.Money;
                    player.PlaceMoney(action.Money);
                }
            }
            else if (action.Type == PlayerActionType.CheckCall)
            {
                player.Call(maxMoneyPerPlayer);
            }
            else //// PlayerActionType.Fold
            {
                player.InHand = false;
            }

            return action;
        }
        public override void EndRound(EndRoundContext context)
        {
            var enemyActions = context.RoundActions.Where(a => a.PlayerName == enemyName).ToList();
            if (enemyActions.Count > 1)
            {
                var enemyLastAction = enemyActions[enemyActions.Count - 1].Action;

                if (enemyLastAction == PlayerAction.Fold())
                {
                    enemyAlwaysRise = false;
                    enemyAlwaysAllIn = false;
                    enemyAlwaysCall = false;

                    return;
                }

                previousRoundLastEnemyAction = enemyLastAction;

                if (currentRoundType == GameRoundType.PreFlop
                && !(enemyAlwaysAllIn || enemyAlwaysCall || enemyAlwaysRise))
                {
                    var enemyFirstPreFlopAction = enemyActions[1].Action;

                    if (enemyFirstPreFlopAction.Type == PlayerActionType.Raise)
                    {
                        enemyRising = true;
                    }
                    else
                    {
                        enemyRising = false;
                    }

                    enemyCardsPrediction = EnemyPredictions.PredictEnemyCardsPreFlop(
                        this.FirstCard,
                        this.SecondCard,
                        enemyFirstPreFlopAction);
                }
            }
        }