""" This file includes a class Hand which implements a hand of five playing
    cards, where cards are defined in the Card class.   

    The Hand class defines the following methods:

    Hand( source, fromDeck ):  creates a new hand object of 5 Cards. This happens
         in one of two ways depending on the value of fromDeck: 
         (1) if fromDeck is True, deal 5 cards from an existing deck
             passed as source, 
         (2) if fromDeck is not True, create the cards from a list of 5 card 
             specifiers passed as source, e.g., ("2S", "9S", "TC", "AH", "4D") 
             will create a hand containing the 2 of Spades, 9 of Spades, 10 of Clubs, 
             Ace of Hearts, and 4 of Diamonds.  Generating a single card from a 
             spec is implemented in the Card class.  You need to check that this
             list is legal (contains exactly 5 legal card specifiers, all distinct).
    h.__str__(): generate the print representation of Hand h, using the
         str function on each of the individual Cards it contains (see the Deck
         class for a model for this);
    h.getCard( i ): recall that h is a hand of 5 Cards.  This provides a 
         way of getting the ith card from the hand, for example, to iterate 
         through the hand in a loop. 

    This file also contains a number of other functions (outside the class), mainly
    to allow evaluating a hand in the sense of playing Poker.  You can have as many
    functions as you need, but you must have the function evaluateHand( hand ). 
    Given a hand, it prints the hand and then the "evaluation" of the hand in 
    the sense of a Poker hand.  This is described in detail in the assignment description.   

"""

################################################################################
#                                                                              #
#                                 Hand Class                                   #
#                                                                              #
################################################################################

# I don't need to import Card, since Deck already does.
from Deck import *

def isLegalCardList( l ):
    """ Check that list l contains 5 legal card specifiers, 
        all distinct. You can assume that it's a list. """
    # You'll need to fill this in
    pass  

class Hand:

    def __init__(self, source, fromDeck = True):
        """ A hand is simply a list of 5 cards, dealt from the deck
            or given as a list of five card specifiers.  If fromDeck
            is True, expect to deal from a deck passed as source. 
            If False, expect source to be a list of five Card specifiers.
            Create the hand from the specified cards.
        """
        if fromDeck:
            if ( len(source) < 5 ):
                print ( "Not enough cards left!" )
                return None
            self.__cards = []
            for i in range(5):
                card = source.deal()              # deal next card
                self.__cards.append(card)         # append it to the hand
        elif not isLegalCardList( source ):
            print("Illegal card list provided.")
        else:
            # fill in this code, to generate a hand from
            # a list of Card specifiers.  You can assume that
            # source is a list,
            pass

    def __str__(self):
        """ Generates the print image of the Hand. """
        pass

    def getCard( self, i ):
        """ Get the ith card from the hand, where 
            i in [0..4]. Return None if i is not
            legal. """
        pass
            
################################################################################
#                                                                              #
#                                Evaluate Hand                                 #
#                                                                              #
################################################################################

def processHand( hand ):
    """ Given a poker hand, create and return two lists which
        record the ranks and suits in the hand. """
    pass

# You'll need to define all of the auxiliary functions called by
# evaluateHand.  Notice that these auxiliary functions don't all
# need both myRanks and mySuits, but I decided to pass them both
# just to make the interface more uniform.  You can change that 
# if you want to.

def hasPair( myRanks, mySuits ):
    pass

# Add other recognizers here; evaluateHand tells you which ones you
# need.  I suggest doing them in "reverse order" so you define the 
# lowest hands first. Hopefully, you'll see why as you code them!

def evaluateHand( hand ):
    myRanks, mySuits = processHand( hand )
    print( hand )
    if hasRoyalFlush( myRanks, mySuits ):
        print( "Royal Flush" )
    elif hasStraightFlush( myRanks, mySuits ):
        print( "Straight Flush" )
    elif hasFourOfAKind( myRanks, mySuits ):
        print( "Four of a kind" )
    elif hasFullHouse( myRanks, mySuits ):
        print( "Full House" )
    elif hasFlush( myRanks, mySuits ):
        print( "Flush" )
    elif hasStraight( myRanks, mySuits ):
        print( "Straight" )
    elif hasThreeOfAKind( myRanks, mySuits ):
        print( "Three of a kind" )
    elif hasTwoPair( myRanks, mySuits ):
        print( "Two pair" )
    elif hasPair( myRanks, mySuits ):
        print( "Pair" )
    else:
        print( "Nothing" )

# This is some test code.  You can modify this or write your
# own.  You certainly should test additional hands. You can run 
# this in interactive mode with:
# 
# from Hand import *
# TestCode()
#
# You can also run this in batch mode by uncommenting the call to:
# TestCode()
#
# and running:
# 
# python3 Hand.py              # or whatever the python command is
#                              # is on your system. 

def TestCode():
    print("\nGenerating and printing deck")
    d = Deck()
    print(d)
    print("\nShuffling deck and printing deck")
    d.shuffle()
    print(d)

    print("\nGenerating hand from deck")
    h = Hand(d, True)
    evaluateHand( h )

    print("\nGenerating hand from list")
    cardSpec = ["as", "ad", "ah", "ac", "2d"]
    h = Hand(cardSpec, False)
    evaluateHand( h )

    print("\nGenerating hand from list")
    cardSpec = ["AS", "2S", "3C", "4H", "5D"]
    h = Hand(cardSpec, False)
    evaluateHand( h )

    print("\nGenerating hand from list")
    cardSpec = ["2s", "9S", "tc", "AH", "4d"]
    h = Hand(cardSpec, False)
    evaluateHand( h )

# TestCode()
