@Override
        public int compare(FrenchCard c1, FrenchCard c2) {
          if (c1.isSuit(FrenchSuit.JOKER) && c2.isSuit(FrenchSuit.JOKER)) return 0;
          if (c1.isSuit(FrenchSuit.JOKER)) return 1;
          if (c2.isSuit(FrenchSuit.JOKER)) return -1;
          if (c1.getValue().equals(c2.getValue())) return 0;

          if (!c1.isValue("J") && !c1.isValue("Q") && !c1.isValue("K") && !c1.isValue("A")) {
            if (c2.isValue("J") || c2.isValue("Q") || c2.isValue("K") || c2.isValue("A")) {
              return -1;
            } else {
              return Integer.compare(
                  Integer.parseInt(c1.getValue()), Integer.parseInt(c2.getValue()));
            }
          } else {
            if (!c2.isValue("J") && !c2.isValue("Q") && !c2.isValue("K") && !c2.isValue("A")) {
              return 1;
            } else {
              if (c1.isValue("J")) return -1;
              else if (c2.isValue("J")) return 1;
              else if (c1.isValue("Q")) return -1;
              else if (c2.isValue("Q")) return 1;
              else if (c1.isValue("K")) return -1;
              else return 1;
            }
          }
        }
  /**
   * Gets the kind of the poker player hand.
   *
   * @return The first element of the array will be the poker hand kind. The following elements of
   *     the array represent the value or values that determines the quality of the poker hand. The
   *     rest of values will represent the card values left, used to solve draws. If player doesn't
   *     have the five hands the method will return null.
   * @example The hand [A A A K K] will return {PokerHand.FULL, A, K}. The hand [Q Q 10 9 5] will
   *     return {PokerHand.PAIR, Q, 10, 9, 5}.
   */
  public ArrayList<Object> getPokerHand() {
    if (playerHand.size() < 5) return null;
    Collections.sort(playerHand, comparator);

    int num_jokers = 0;
    for (FrenchCard c : playerHand) {
      if (c.isSuit(FrenchSuit.JOKER)) num_jokers++;
    }

    if (num_jokers == 5) {
      return new ArrayList(Arrays.asList(PokerHand.REPOKER, "A"));
    }

    Integer frequencies[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    String values[] = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"};

    ArrayList<String> cardValues = new ArrayList();
    for (FrenchCard c : playerHand) {
      if (!c.isSuit(FrenchSuit.JOKER)) cardValues.add(c.getValue());
    }

    for (int i = 0; i < 13; i++) {
      for (FrenchCard c : playerHand) {
        frequencies[i] += c.isValue(values[i]) ? 1 : 0;
      }
      frequencies[i] += num_jokers;
    }

    ArrayList<Object> pokerHand = new ArrayList();
    PokerHand hand = null;
    int reps = Collections.max(Arrays.asList(frequencies));
    switch (reps) {
      case 5:
        hand = PokerHand.REPOKER;
        pokerHand.add(hand);
        pokerHand.add(values[Arrays.asList(frequencies).indexOf(5)]);
        break;
      case 4:
        hand = PokerHand.POKER; // 5 A A A A  // 3 3 3 3 5
        pokerHand.add(hand);
        pokerHand.add(values[Arrays.asList(frequencies).lastIndexOf(4)]);
        cardValues.removeAll(
            Collections.singleton(values[Arrays.asList(frequencies).lastIndexOf(4)]));
        pokerHand.add(cardValues.get(0));
        break;
      case 3:
        if (Collections.frequency(Arrays.asList(frequencies), 2 + num_jokers) >= num_jokers + 1) {
          hand = PokerHand.FULL;
          pokerHand.add(hand);
          pokerHand.add(values[Arrays.asList(frequencies).lastIndexOf(3)]);
          cardValues.removeAll(
              Collections.singleton(values[Arrays.asList(frequencies).lastIndexOf(3)]));

          pokerHand.add(cardValues.get(0));
        } else {
          hand = PokerHand.THREESOME;
          pokerHand.add(hand);
          pokerHand.add(values[Arrays.asList(frequencies).lastIndexOf(3)]);
          cardValues.removeAll(
              Collections.singleton(values[Arrays.asList(frequencies).lastIndexOf(3)]));
          pokerHand.add(cardValues.get(1));
          pokerHand.add(cardValues.get(0));
        }
        break;
      case 2:
        if (Collections.frequency(Arrays.asList(frequencies), 2) == 2) {
          hand = PokerHand.TWO_PAIR;
          pokerHand.add(hand);
          pokerHand.add(values[Arrays.asList(frequencies).lastIndexOf(2)]);
          pokerHand.add(values[Arrays.asList(frequencies).indexOf(2)]);
          pokerHand.add(values[Arrays.asList(frequencies).indexOf(1)]);
        } else {
          hand = PokerHand.PAIR;
          pokerHand.add(hand);
          pokerHand.add(values[Arrays.asList(frequencies).lastIndexOf(2)]);
          cardValues.removeAll(
              Collections.singleton(values[Arrays.asList(frequencies).lastIndexOf(2)]));
          pokerHand.add(cardValues.get(2));
          pokerHand.add(cardValues.get(1));
          pokerHand.add(cardValues.get(0));
        }
        break;
    }

    boolean isFlush = true;
    FrenchSuit flushSuit = null;
    for (int i = 0; i < 5 && isFlush; i++) {
      if (flushSuit != null
          && !playerHand.get(i).isSuit(flushSuit)
          && !playerHand.get(i).isSuit(FrenchSuit.JOKER)) {
        isFlush = false;
      }
      if (flushSuit == null && !playerHand.get(i).isSuit(FrenchSuit.JOKER)) {
        flushSuit = playerHand.get(i).getSuit();
      }
    }

    boolean isStraight = true;
    int straightFirstIndex = Arrays.asList(values).indexOf(playerHand.get(0).getValue());
    int currentIndex = straightFirstIndex;

    for (int i = 1; i < 5 && isStraight; i++) {
      if (playerHand.get(i).getSuit() != FrenchSuit.JOKER
          && (Arrays.asList(values).indexOf(playerHand.get(i).getValue()) == currentIndex
              || Arrays.asList(values).indexOf(playerHand.get(i).getValue()) - straightFirstIndex
                  > 4)) {
        isStraight = false;
      }
      currentIndex = Arrays.asList(values).indexOf(playerHand.get(i).getValue());
    }
    if (isStraight && straightFirstIndex > 8) straightFirstIndex = 8; // Para Jokers, Q, K, A

    if (isStraight && isFlush && reps < 5) {
      pokerHand.clear();
      if (values[straightFirstIndex] == "10") {
        pokerHand.add(PokerHand.ROYAL_FLUSH);
      } else {
        pokerHand.add(PokerHand.STRAIGHT_FLUSH);
        pokerHand.add(values[straightFirstIndex + 4]);
      }
    } else if (isFlush && reps < 4) {
      pokerHand.clear();
      pokerHand.add(PokerHand.FLUSH);
      for (int i = 4; i >= 0; i--) {
        if (playerHand.get(i).isSuit(FrenchSuit.JOKER)) pokerHand.add("A");
        else pokerHand.add(playerHand.get(i).getValue());
      }
    } else if (isStraight && reps < 4 && hand != PokerHand.FULL) {
      pokerHand.clear();
      pokerHand.add(PokerHand.STRAIGHT);
      pokerHand.add(values[straightFirstIndex + 4]);
    } else if (pokerHand.isEmpty()) {
      pokerHand.add(PokerHand.HIGHCARD);
      pokerHand.add(playerHand.get(4).getValue());
      pokerHand.add(playerHand.get(3).getValue());
      pokerHand.add(playerHand.get(2).getValue());
      pokerHand.add(playerHand.get(1).getValue());
      pokerHand.add(playerHand.get(0).getValue());
    }
    return pokerHand;
  }