from graphics import Text, GraphWin, Point

class ScoreCard:
    """
    Maintains a Yahtzee scorecard.
    """

    def __init__(self, ui='gui'):
        """
        This is the constructor for the ScoreCard class.

        Categories are assigned a numeric value as follows:
            Ones              =>  0
            Twos              =>  1
            Threes            =>  2
            Fours             =>  3
            Fives             =>  4
            Sixes             =>  5
            Three of a Kind   =>  6
            Four of a Kind    =>  7
            Full House        =>  8
            Sm Straight       =>  9
            Lg Straight       => 10
            Chance            => 11 
            Yahtzee           => 12
            Upper Bonus       => 13
            Yahtzee Bonus     => 14
            Total             => 15
        """
        self._cats=["Ones","Twos","Threes","Fours","Fives","Sixes",
                    "Upper Bonus",
                    "3 of a Kind", "4 of a Kind", "Full House", 
                    "Sm Straight", "Lg Straight", "Chance", "Yahtzee",
                    "Yahtzee Bonus",
                    "Total"]

        self._pos=[0,1,2,3,4,5,7,8,9,10,11,12,13,6,14,15]

        self._scores = [None]*16
        self._scores[6] = 0
        self._scores[14] = 0
        self._scores[15] = 0

        self._card = None
        self._startletter = 'N'

        if ui == 'gui':
            self._initializeCard()


    def _initializeCard(self):
        self._card = GraphWin("Yahtzee", 300, 600)

        y = 40
        c1 = 60
        c2 = c1 + 100
        c3 = c2 + 75
        vspace = 30
        picker = ord(self._startletter)
        self._labels = []
        self._slabels = []
        self._plabels = []
        for i in range(16):
            c = self._cats[i]
            self._labels.append(Text(Point(c1, y), c))
            self._slabels.append(Text(Point(c2, y), '-'))

            if i not in [6, 14, 15]:
                self._plabels.append(Text(Point(c3, y), chr(picker)))
                picker += 1
            else:
                y += vspace

            y += vspace

            
        for l in self._labels:
            l.draw(self._card)

        for s in self._slabels:
            s.draw(self._card)

        self._updateScores()

        for p in self._plabels:
            p.draw(self._card)
            


    def __del__(self):
        try:
            if self._card == None or self._card.isClosed():
                self._printscores(['']*15)
            else:
                print "Click the scorecard to end your game."
                self._card.getMouse()
                self._card.close()
        except:
            pass


    def isUsed(self, category):
        """ 
        Returns True if specified category has already been picked;
        otherwise returns False.
        """

        return not self.isFree(category)


    def isFree(self, category):
        """ 
        Returns True if specified category has not yet been picked;
        otherwise returns False.
        """
        return self._scores[self._pos[category]] == None


    def getScore(self, category):
        """
        Returns the current score assigned to this category; if
        the category is free, returns 0.
        """
        if self.isFree(category):
            return 0
        else:
            return self._scores[self._pos[category]]



    def setScore(self, category, value):
        """
        Set the score of the specified category to value.
        """

        pos = self._pos[category]
        self._scores[pos] = value

        if pos in [6, 14, 15]:
            pass
        elif pos < 6:
            self._plabels[pos].setText('')
        else:
            self._plabels[pos-1].setText('')

        self._updateScores()


    def _updateScores(self):
        for slot in range(16):
            if self._scores[slot] != None:
                self._displayScore(slot, self._scores[slot])
            else:
                self._displayScore(slot, '-', free=True)


    def _displayScore(self, slot, value, free=False):
        if self._card == None:
            return

        self._slabels[slot].setText(str(value))
        if free:
            self._slabels[slot].setStyle('italic')
            self._slabels[slot].setTextColor('red')
        else:
            if slot in [6, 14]:
                self._slabels[slot].setStyle('normal')
                self._slabels[slot].setTextColor('blue')
            elif slot == 15:
                self._slabels[slot].setStyle('bold')
                self._slabels[slot].setTextColor('black')
            else:
                self._slabels[slot].setStyle('normal')
                self._slabels[slot].setTextColor('black')
                
            



    def _printscores(self, posslist):
        """
        Shows table of yahtzee scores.

        Includes scores of previously selected categories,
        possible scores for current dice roll, and menu 
        labels for selecting a new category 
        """

        shortFmt="%14s%8s"
        sfmt=shortFmt+"%9s%7s"
        print sfmt % ("Slot","Current","Possible","Choice")
        print "-"*38

        for i in range(15):
            sval = self._scores[i]
            if sval is None:
                sval = ""
            if i in [6, 14, 15]:
                print sfmt % (self._cats[i], sval, "", "")
            else:
                p = i
                if i > 5:
                    p -= 1
                print sfmt % (self._cats[i], sval, posslist[p],
                              chr(ord(self._startletter)+p))
                

    def displayPossibles(self, posslist):
        """
        Shows table of yahtzee scores.

        Includes scores of previously selected categories,
        possible scores for current dice roll, and menu 
        labels for selecting a new category 
        """

        if self._card == None or self._card.isClosed():
            self._printscores(posslist)
            self._card = None
            pass
        else:
            for i in range(13):
                slot = self._pos[i]
                if self.isFree(i):
                    self._displayScore(slot, posslist[i], True)
