public int CompareHands(IHand firstHand, IHand secondHand)
        {
            if (firstHand.Equals(secondHand))
            {
                throw new ArgumentException("Can not compare hands of the same type");
            }

            foreach (var card in firstHand.Cards)
            {
                if (secondHand.Cards.Contains(card))
                {
                    throw new ArgumentException("One card can not be held by two players!");
                }
            }

            var firstHandType  = GetHandType(firstHand);
            var secondHandType = GetHandType(secondHand);

            if (firstHandType != secondHandType)
            {
                return(((int)firstHandType).CompareTo((int)secondHandType));
            }

            if (firstHandType == HandType.Pair)
            {
                var firstGroupedByFace  = firstHand.Cards.GroupBy(c => c.Face).OrderByDescending(g => g.Count()).ToArray();
                var secondGroupedByFace = secondHand.Cards.GroupBy(c => c.Face).OrderByDescending(g => g.Count()).ToArray();

                var comparisonResult = firstGroupedByFace[0].First().Face.CompareTo(secondGroupedByFace[0].First().Face);

                if (comparisonResult == 0)
                {
                    var firstOtherCards  = firstGroupedByFace.Skip(1).Select(g => g.First()).OrderByDescending(c => c.Face).ToArray();
                    var secondOtherCards = secondGroupedByFace.Skip(1).Select(g => g.First()).OrderByDescending(c => c.Face).ToArray();

                    for (int i = 0; i < firstOtherCards.Length; i++)
                    {
                        var comparison = firstOtherCards[i].Face.CompareTo(secondOtherCards[i].Face);
                        if (comparison != 0)
                        {
                            comparisonResult = comparison;
                            break;
                        }
                    }
                }

                return(comparisonResult);
            }
            else if (firstHandType == HandType.TwoPairs)
            {
                var firstGroupedByFace  = firstHand.Cards.GroupBy(c => c.Face).OrderByDescending(g => g.Count()).ToArray();
                var secondGroupedByFace = secondHand.Cards.GroupBy(c => c.Face).OrderByDescending(g => g.Count()).ToArray();

                var firstHandCards = new List <ICard>();
                firstHandCards.Add(firstGroupedByFace[0].First());
                firstHandCards.Add(firstGroupedByFace[1].First());
                firstHandCards = firstHandCards.OrderByDescending(c => c.Face).ToList();
                firstHandCards.Add(firstGroupedByFace[2].First());

                var secondHandCards = new List <ICard>();
                secondHandCards.Add(secondGroupedByFace[0].First());
                secondHandCards.Add(secondGroupedByFace[1].First());
                secondHandCards = secondHandCards.OrderByDescending(c => c.Face).ToList();
                secondHandCards.Add(secondGroupedByFace[2].First());

                var comparisonResult = firstHandCards[0].Face.CompareTo(secondHandCards[0].Face);

                if (comparisonResult == 0)
                {
                    comparisonResult = firstHandCards[1].Face.CompareTo(secondHandCards[1].Face);

                    if (comparisonResult == 0)
                    {
                        comparisonResult = firstHandCards[2].Face.CompareTo(secondHandCards[2].Face);
                    }
                }

                return(comparisonResult);
            }
            else if (firstHandType == HandType.FullHouse)
            {
                var firstGroupedByFace  = firstHand.Cards.GroupBy(c => c.Face).OrderByDescending(g => g.Count()).ToArray();
                var secondGroupedByFace = secondHand.Cards.GroupBy(c => c.Face).OrderByDescending(g => g.Count()).ToArray();

                var comparisonResult = firstGroupedByFace[0].First().Face.CompareTo(secondGroupedByFace[0].First().Face);
                return(comparisonResult);
            }
            else if (firstHandType == HandType.Flush || firstHandType == HandType.HighCard)
            {
                var firstSortedByFace  = firstHand.Cards.OrderByDescending(c => c.Face).ToArray();
                var secondSortedByFace = secondHand.Cards.OrderByDescending(c => c.Face).ToArray();

                var comparisonResult = 0;

                for (int i = 0; i < firstSortedByFace.Length; i++)
                {
                    comparisonResult = firstSortedByFace[i].Face.CompareTo(secondSortedByFace[i].Face);
                    if (comparisonResult != 0)
                    {
                        break;
                    }
                }

                return(comparisonResult);
            }
            else if (firstHandType == HandType.ThreeOfKind || firstHandType == HandType.FourOfKind)
            {
                var firstGroupedByFace  = firstHand.Cards.GroupBy(c => c.Face).OrderByDescending(g => g.Count()).ToArray();
                var secondGroupedByFace = secondHand.Cards.GroupBy(c => c.Face).OrderByDescending(g => g.Count()).ToArray();

                var comparisonResult = firstGroupedByFace[0].First().Face.CompareTo(secondGroupedByFace[0].First().Face);
                return(comparisonResult);
            }

            // straight or straightflush
            else
            {
                var firstSortedByFace  = firstHand.Cards.OrderByDescending(c => c.Face).ToArray();
                var secondSortedByFace = secondHand.Cards.OrderByDescending(c => c.Face).ToArray();

                var comparisonResult = firstSortedByFace[0].Face.CompareTo(secondSortedByFace[0].Face);
                return(comparisonResult);
            }
        }
        public int CompareHands(IHand firstHand, IHand secondHand)
        {
            // highcard, pair, twopair, set, straight, flush, fullhouse, four of a kind, straight flush
            // 1         2     3        4    5         6      7          8               9

            if (!IsValidHand(firstHand) || !IsValidHand(secondHand))
            {
                throw new System.InvalidOperationException("Invalid hand.");
            }

            if (firstHand.Equals(secondHand))
            {
                return(0);
            }

            var firstRank  = 0;
            var secondRank = 0;

            //firstHand
            if (IsStraightFlush(firstHand))
            {
                firstRank = 9;
            }
            else if (IsFourOfAKind(firstHand))
            {
                firstRank = 8;
            }
            else if (IsFullHouse(firstHand))
            {
                firstRank = 7;
            }
            else if (IsFlush(firstHand))
            {
                firstRank = 6;
            }
            else if (IsStraight(firstHand))
            {
                firstRank = 5;
            }
            else if (IsThreeOfAKind(firstHand))
            {
                firstRank = 4;
            }
            else if (IsTwoPair(firstHand))
            {
                firstRank = 3;
            }
            else if (IsOnePair(firstHand))
            {
                firstRank = 2;
            }
            else if (IsHighCard(firstHand))
            {
                firstRank = 1;
            }
            //secondHand
            if (IsStraightFlush(secondHand))
            {
                secondRank = 9;
            }
            else if (IsFourOfAKind(secondHand))
            {
                secondRank = 8;
            }
            else if (IsFullHouse(secondHand))
            {
                secondRank = 7;
            }
            else if (IsFlush(secondHand))
            {
                secondRank = 6;
            }
            else if (IsStraight(secondHand))
            {
                secondRank = 5;
            }
            else if (IsThreeOfAKind(secondHand))
            {
                secondRank = 4;
            }
            else if (IsTwoPair(secondHand))
            {
                secondRank = 3;
            }
            else if (IsOnePair(secondHand))
            {
                secondRank = 2;
            }
            else if (IsHighCard(secondHand))
            {
                secondRank = 1;
            }

            if (firstRank > secondRank)
            {
                return(-1);
            }
            if (firstRank < secondRank)
            {
                return(1);
            }
            if (firstRank == secondRank) // same ranked hands
            {
                switch (firstRank)
                {
                case 1: return(BothHighCard(firstHand, secondHand, 4));

                case 2: return(BothOnePair(firstHand, secondHand));

                case 3: return(BothTwoPair(firstHand, secondHand));

                case 4: return(BothThreeOfAKind(firstHand, secondHand));

                case 5: return(BothStraight(firstHand, secondHand));

                case 6: return(BothFlush(firstHand, secondHand));

                case 7: return(BothFullHouse(firstHand, secondHand));

                case 8: return(BothFourOfAKind(firstHand, secondHand));

                case 9: return(BothStraightFlush(firstHand, secondHand));
                }
            }
            throw new System.InvalidOperationException("Error");
        }