"""
Some utility functions for creating and drawing boggle boards.
"""

import random

try:
    import cs1graphics
except ImportError:
    cs1graphics = None


cubes16 = ['delrvy', 'achops', 'hlnnrz', 'eiosst',
           'twvhre', 'itystd', 'joabob', 'quihmn',
           'oaottw', 'hngwee', 'afkpfs', 'eeaang',
           'derlix', 'iouctm', 'usneei', 'rtlyet']

# Perhaps an older set of cubes?
#cubes16 = ['forixb', 'moqabj', 'gurilw', 'setupl',
#           'cmpdae', 'acitao', 'slcrae', 'romash',
#           'nodesw', 'hefiye', 'onudtk', 'tevign',
#           'anedvz', 'pinesh', 'abilyt', 'gkyleu']

class Die:
    """
    A class representing a single die in the game.
    """
    def __init__(self,v):
        """
        Creates a new dice, with value v displayed.
        """
        self._value = v
        self._highlighted = False

    def setHighlight(self):
        """
        Highlights the die.

        This only has an effect in conjunction with drawing a board.
        """
        self._highlighted = True
        
    def clearHighlight(self):
        """
        Un-highlights the die.

        This only has an effect in conjunction with drawing a board.
        """
        self._highlighted = False

    def getValue(self):
        return self._value

    def __repr__(self):
        return self._value.capitalize()


def newBoard(seed=None):
    """
    Creates a new board and returns it.

    A board is actually a list of columns, with each column being a
    list of dice.  Thus board[x][y] is an individual die at the
    specified position.
    """
    gen = random.Random()
    if seed == None:
        seed = raw_input("What board number? [default: random] ")
        try:
            seed = int(seed)
        except ValueError:
            seed = gen.randint(0,10000000)
            print "Using game number",seed
    gen.seed(seed)

    board = []
    pick = range(16)
    gen.shuffle(pick)

    for x in range(4):
        board.append(list())
        for y in range(4):
            side = gen.choice(cubes16[pick[4*x+y]])
            if side=='q': side='qu'
            board[x].append(Die(side))
    return board


def clearHighlights(board):
    for x in range(4):
        for y in range(4):
            board[x][y].clearHighlight()



INSET_WIDTH = 1
BORDER_WIDTH = 2
DIE_WIDTH = 8
OVERALL_WIDTH = 2*INSET_WIDTH + 2*BORDER_WIDTH + 4*DIE_WIDTH
CENTER = OVERALL_WIDTH / 2.0
DIE_PERCENT = 1.0
BASECOLOR = "darkblue"
DIECOLOR = "white"
HIGHLIGHTCOLOR = "yellow"
TEXTCOLOR = "darkblue"
TEXTSIZE = 5

def _roundFactory():
    round = cs1graphics.Circle()
    round.setRadius(BORDER_WIDTH/2.0)
    round.setBorderColor(BASECOLOR)
    round.setFillColor(BASECOLOR)
    return round

def _dieFactory(letter,highlighted):
    sq = cs1graphics.Square()
    sq.setSize(DIE_WIDTH * DIE_PERCENT)
    sq.setBorderColor(BASECOLOR)
    if highlighted:
        sq.setFillColor(HIGHLIGHTCOLOR)
    else:
        sq.setFillColor(DIECOLOR)
    sq.setDepth(2)
    text = cs1graphics.Text()
    text.setMessage(letter)
    text.setFontSize(TEXTSIZE)
    text.setDepth(1)
    text.setFontColor(TEXTCOLOR)
    die = cs1graphics.Layer()
    die.add(sq)
    die.add(text)
    die.setDepth(-1)
    return die

def drawBoard(board,canvas=None):
    """
    Draws the given board.   If a canvas is given, then it draws it graphically.
    Otherwise, it creates a textual representation.
    """
    if canvas and cs1graphics:
        canvas.setAutoRefresh(False)
        total = float(min(canvas.getWidth(), canvas.getHeight()))
        lay = cs1graphics.Layer()
        canvas.clear()
        canvas.add(lay)
        lay.scale(total/OVERALL_WIDTH)

        offset = INSET_WIDTH + BORDER_WIDTH/2.0

        round1 = _roundFactory()
        round1.move(offset, offset)
        round2 = _roundFactory()
        round2.move(OVERALL_WIDTH - offset, offset)
        round3 = _roundFactory()
        round3.move(offset, OVERALL_WIDTH - offset)
        round4 = _roundFactory()
        round4.move(OVERALL_WIDTH - offset, OVERALL_WIDTH - offset)
        lay.add(round1)
        lay.add(round2)
        lay.add(round3)
        lay.add(round4)

        base1 = cs1graphics.Rectangle(OVERALL_WIDTH - BORDER_WIDTH - 2*INSET_WIDTH,
                                      OVERALL_WIDTH - 2*INSET_WIDTH)
        base1.setBorderColor(BASECOLOR)
        base1.setFillColor(BASECOLOR)
        base1.move(CENTER, CENTER)
        lay.add(base1)
        base2 = cs1graphics.Rectangle(OVERALL_WIDTH - 2*INSET_WIDTH,
                                      OVERALL_WIDTH - BORDER_WIDTH - 2*INSET_WIDTH)
        base2.setBorderColor(BASECOLOR)
        base2.setFillColor(BASECOLOR)
        base2.move(CENTER, CENTER)
        lay.add(base2)

        for x in range(4):
            for y in range(4):
                die = _dieFactory(board[x][y].getValue().capitalize(),board[x][y]._highlighted)
                die.move(CENTER + (x-1.5)*DIE_WIDTH, CENTER + (y-1.5)*DIE_WIDTH)
                lay.add(die)
        
        canvas.setAutoRefresh(True)


    else:
        for row in range(4):
            for col in range(4):
                print "%-2s"%board[col][row],
            print

