# card.py
# Lillian Lee (LJL2) and Steve Marschner (srm2)
# Mar 11, 2013

"""Module providing a type for playing cards

Implementation adapted from chapter 18 of the course text, _Think Python_,
by Allen B. Downey.
"""


SUIT_NAMES = ['Clubs', 'Diamonds', 'Hearts', 'Spades']
NUM_SUITS = len(SUIT_NAMES)

# starts at None so that we can treat RANK_NAMES as a translation table:
# RANK_NAME[1] is 'Ace', RANK_NAME[13] is 'King', etc.
RANK_NAMES = [None, 'Ace', '2', '3', '4', '5', '6', '7',
              '8', '9', '10', 'Jack', 'Queen', 'King']
NUM_RANKS = 13


class Card(object):
    """Represents a standard playing card.

    Instance variables:
        suit [int]: the suit of this particular card. The name of this
                    suit is given by SUIT_NAMES[suit]. Always in 0..NUM_SUITS-1
        rank [int]: the rank of this particular card.  The name of this rank
                    is given by RANK_NAMES[rank].  Always in 1..NUM_RANKS

    Hence, if we execute c = Card(0, 12), SUIT_NAMES[c.suit] is 'Clubs'
    and RANK_NAMES[c.rank] is '12' and this card is the Queen of Clubs.

    """

    def __init__(self, suit=0, rank=1, code=None):
        """Initializer: A new card whose suit encoding is suit and rank
        encoding is rank.  Alternatively, the suit and rank can be encoded
        together in a two-character string like '3H' (3 of hearts) or 'KS'
        (king of spades).  Use 'T' for Ten.

        Example: if we execute c = Card(0, 12), then this card is the Queen of
        Clubs, since SUIT_NAMES[c.suit] is 'Clubs' and RANK_NAMES[c.rank] is 12.
        The same card could be created by Card('QC').

        Preconditions: suit in 0..NUM_SUITS-1 (inclusive) and
        rank in 1..NUM_RANKS (inclusive), or code[0] in 'A23456789TJQK' and
        card[1] in 'CDHS'."""
        if code:
            suit = 'CDHS'.index(code[1])
            rank = ' A23456789TJQK'.index(code[0])
        self.suit = suit
        self.rank = rank

    def __str__(self):
        """Readable string representation of this card.
        Example: '2 of Hearts'"""
        return RANK_NAMES[self.rank] + ' of ' + SUIT_NAMES[self.suit]

    def __eq__(self, other):
        """Equality determined by equality of attributes"""
        return (isinstance(other,Card) and
                (self.suit, self.rank) == (other.suit, other.rank))

    def __ne__(self, other):
        """Equality determined by equality of attributes"""
        return not self.__eq__(other)

    def __cmp__(self, other):
        """Compare cards by poker ordering, Aces high.  Return < 0 if self is
        ranked lower; > 0 if other is ranked lower; 0 if the cards are the same.
        """
        if (self.rank == other.rank):
            return cmp(self.suit, other.suit)
        else:
            return cmp(14 if self.rank == 1 else self.rank,
                       14 if other.rank == 1 else other.rank)

def full_deck():
    """Returns: list of the standard 52 cards"""
    output = []  # list of cards so far to be returned
    for suit in range(NUM_SUITS):
        for rank in range(1,NUM_RANKS+1):  # skip the None value
            output.append(Card(suit,rank))
    return output


def print_cards(clist):
    """Print cards in list clist.

    Precondition:  clist is a list of Cards, possibly empty."""
    for c in clist:
        print str(c)