"""
 deck.py

 Zelle exercise 11 from chapter 10 
 and exercise 15 from chapter 11

 (1) Implement a class to represent a playing card,
     including its blackjack_value (1 to 10).
 (2) Implement a class to represent a deck, including these methods

     constructor        Creates a new deck of 52 cards in a standard order.
     shuffle            Randomizes the order of the cards.
     dealCard           Returns a single card from the top of the deck 
                        and removes the card from the deck.
     cardsLeft          Returns the number of cards remaining in the deck.

 Jim Mahoney | cs.bennington.college | April 2021 | MIT License
"""

import random

suits = ('c', 'd', 'h', 's')
ranks = tuple(range(1, 14))   # (1, 2, 3, ...., 11, 12, 13)
suitnames = {'c': 'Clubs', 'd': 'Diamonds', 'h': 'Hearts', 's': 'Spades'}
ranknames = (None, 'Ace', 'Two', 'Three', 'Four', 'Five', 'Six',
             'Seven', 'Eight', 'Nine', 'Ten', 'Jack', 'Queen', 'King')
             
class Card:
    """ A playing card """
    def __init__(self, rank=None, suit=None):
        if rank == None:
            rank = random.choice(ranks)
        if suit == None:
            suit = random.choice(suits)
        self.rank = rank
        self.suit = suit
    def __str__(self):
        return f"{ranknames[self.rank]} of {suitnames[self.suit]}"
    def blackjack_value(self):
        """ Return blackjack card value, i.e. 10 for Jack,Queen,King """
        if self.rank >= 10:
            return 10
        else:
            return self.rank

class Deck:
    """ A deck of 52 cards """
    def __init__(self):
        self.cards = []
        for suit in suits:
            for rank in ranks:
                self.cards.append(Card(rank, suit))
    def deal_card(self):
        """ Return and remove the top card """
        return self.cards.pop()
    def shuffle(self):
        """ shuffle cards in place """
        random.shuffle(self.cards)
    def cards_left(self):
        """ Return number of cards remaining """
        return len(self.cards)

def main():
    print("-- unshuffled -- ")
    deck = Deck()
    for i in range(5):
        card = deck.deal_card()
        print(' ', card, 'with blackjack value', card.blackjack_value())
    print("There are", deck.cards_left(), "cards left.")
    deck.shuffle()
    print("-- continuing after shuffling --")
    for i in range(5):
        print(' ', deck.deal_card())
    print("There are", deck.cards_left(), "cards left.")        

if __name__ == '__main__':
    main()