# L-18.5 MCS 260 Mon 28 Jul 2014 : life.py
"""
GUI for Conway's game of life
"""

from Tkinter import Tk, Scale, Canvas, Button, Label
from Tkinter import IntVar, W, E, N, S, ALL
from numpy import zeros
import game

class GameOfLife(object):
    """
    GUI to the game of life
    """
    def __init__(self, wdw, r, c, m, delay):
        """
        The GUI consists of a canvas, scale, start and stop button.
        The scale controls the speed of the animation, initialized
        by the variable delay on input.
        On canvas there are r rows and c columns of squares of size m.
        """
        wdw.title('the game of life')
        self.rows = r      # number of rows on canvas
        self.cols = c      # number of columns on canvas
        self.size = m      # size of the squares on canvas
        self.dly = IntVar()
        self.grow = False  # state of the animation
        self.grid = zeros((r, c), bool)
        self.scl = Scale(wdw, orient='horizontal', \
            from_=0, to=300, tickinterval=50, resolution=1, \
            length=self.cols, variable=self.dly)
        self.scl.grid(row=0, column=0, columnspan=2, sticky=W+E+N+S)
        self.scl.set(delay)
        self.cnv = Canvas(wdw, width=m*self.cols+2*m, \
            height=m*self.rows+2*m,bg ='white')
        self.lbl = Label(wdw, text="scale controls the delay time")
        self.lbl.grid(row=1, column=0, columnspan=2)
        self.cnv.grid(row=2, column=0, columnspan=2)
        self.bt0 = Button(wdw, text='start', command = self.start)
        self.bt0.grid(row=3, column=0, sticky=W+E)
        self.bt1 = Button(wdw, text='stop', command = self.stop)
        self.bt1.grid(row=3, column=1, sticky=W+E)

    def draw_cells(self):
        """
        Draws the cells on canvas.
        """
        msz = self.size
        self.cnv.delete(ALL)
        for i in range(0, self.rows):
            for j in range(0, self.cols):
                if self.grid[i, j]:
                    (xpt, ypt) = (msz*(j + 1), msz*(i + 1))
                    self.cnv.create_rectangle(xpt, ypt, \
                        xpt+msz, ypt+msz, fill="green")

    def animate(self):
        """
        Performs the animation.
        """
        while self.grow:
            self.grid = game.update(self.grid)
            self.cnv.after(self.dly.get())
            self.draw_cells()
            self.cnv.update()

    def start(self):
        """
        At the start of the animation, a random configuration
        of cells is generated and the animate method is called.
        """
        game.init_random(self.grid)
        self.grow = True
        self.draw_cells()
        self.animate()

    def stop(self):
        """
        Stops the animation.
        """
        self.grow = False

def main():
    """
    Sets the dimensions of the canvas,
    number of rows, columns, and size of squares,
    before launching the main event loop of the GUI.
    """
    top = Tk()
    # rraw = raw_input('Give number of rows (e.g. 40) : ')
    # craw = raw_input('Give number of columns (e.g. 80) : ')
    # mraw = raw_input('Give size of squares (e.g. 10) : ')
    # (row, col, msz) = (int(rraw), int(craw), int(mraw))
    (row, col, msz) = (40, 80, 10)
    dly = 60  # delay for next frame
    show = GameOfLife(top, row, col, msz, dly)
    top.mainloop()

if __name__ == "__main__":
    main()
