/**
   * Returns player's card.
   *
   * @param player who is on turn.
   * @return Card object instance or null.
   */
  public Card getPlayMethodCard(final Player player) {
    final Card attackCard = game.getTrickCards().getAttackCard();
    if (attackCard != null && canHook(player, attackCard.getSuit())) {
      if (player.getCards().hasSuitCard(attackCard.getSuit())) {
        final Card handCard = game.getTrickCards().getHandAttackSuitCard();
        final Card card = player.getCards().findMaxSuitCard(attackCard.getSuit());

        if (card != null && handCard != null) {
          if (isMeterSuitCard(player, card) && card.compareTo(handCard) > 0) {
            return card;
          }

          if (isMaxSuitCardLeft(card, true)) {
            Card maxAboveCard = player.getCards().findMinAboveCard(handCard);
            if (maxAboveCard != null) {
              return maxAboveCard;
            }
          } else {
            if (card.compareTo(handCard) > 0) {
              return card;
            }
          }
        }
      }
    }
    return null;
  }
  /**
   * Returns player's card.
   *
   * @param player who is on turn.
   * @param trump suit.
   * @return Card object instance or null.
   */
  public Card getPlayMethodCard(final Player player, final Suit trump) {
    Card result = null;
    for (final SuitIterator iterator = Suit.iterator(); iterator.hasNext(); ) {
      final Suit suit = iterator.next();
      final Card card = player.getCards().findMinSuitCard(suit);

      if (card != null && !suit.equals(trump)) {
        final int suitCount = player.getCards().getSuitCount(suit);
        final boolean isSingle = suitCount == 1;
        final boolean isMeter = suitCount + getPassedSuitCardsCount(suit) == Rank.getRankCount();

        final Card max = player.getCards().findMaxSuitCard(suit);
        final boolean powerSuit = max != null && isMaxSuitCardLeft(max, true);

        if (isSingle
            && !powerSuit
            && !isMeter
            && max != null
            && max.compareRankTo(Rank.King) <= 0) {
          if (result == null || result.compareRankTo(card) > 0) {
            result = card;
          }
        }
      }
    }
    return result;
  }
  /**
   * Returns player's card.
   *
   * @param player who is on turn.
   * @return Card object instance or null.
   */
  public Card getPlayMethodCard(final Player player) {
    for (final SuitIterator iterator = Suit.iterator(); iterator.hasNext(); ) {
      final Suit suit = iterator.next();
      final int count = player.getCards().getSuitCount(suit);
      final Card jack = player.getCards().findCard(Rank.Jack, suit);
      final Card nine = player.getCards().findCard(Rank.Nine, suit);

      if (jack == null
          && nine != null
          && count > SINGLE_CARD_COUNT
          && !isMaxSuitCardLeft(nine, false)) {
        Player thirdDefencePlayer = getThirdDefencePlayer();
        if (!isPlayerSuitAnnounce(thirdDefencePlayer, suit)) {
          return player.getCards().findMinSuitCard(suit);
        }
      }
    }
    return null;
  }
  private boolean canHook(final Player player, final Suit suit) {
    if (isFirstDefencePosition()) {
      Player next = game.getPlayerAfter(player);
      Player afterNext = game.getPlayerAfter(next);

      return next.getMissedSuits().contains(suit) && afterNext.getMissedSuits().contains(suit);
    } else if (isSecondDefencePosition()) {
      Player next = game.getPlayerAfter(player);

      return next.getMissedSuits().contains(suit);
    } else if (isThirdDefencePosition()) {
      return true;
    }

    return false;
  }
 /**
  * The method which returns the result of condition.
  *
  * @param player which has to declare next game announce.
  * @return boolean true if the condition fits, false otherwise.
  */
 public boolean process(final Player player) {
   final int rankCount = player.getCards().getRankCounts(rank);
   return rankCount >= count;
 }