#! /usr/bin/env python3

"""draw a 2D cellular automaton: Conway's game of life"""

import time
import math
import sys

sys.path.append('../emergent-behavior')
from conway_life import *

## we use the tkinter widget set; this seems to come automatically
## with python3 on ubuntu 16.04, but on some systems one might need to
## install a package with a name like python3-tk
from tkinter import *

color_map = ['black', 'white', 'red', 'green', 'blue', 'yellow']

def main():
    nx = 200
    ny = 200
    scale = 5                   # how many pixels per cell
    canvas_width = scale*nx
    canvas_height = scale*ny
    n_steps = 1000
    paused = False

    ## prepare a basic canvas
    root = Tk()
    life_canvas = Canvas(root, 
                         width=canvas_width,
                         height=canvas_height)
    life_canvas.bind("<ButtonPress-1>", lambda evt: mouse_press(evt, board,
                                                                scale, paused))
    life_canvas.bind("<ButtonRelease-1>", lambda evt: mouse_release(evt, board, 
                                                                    scale, paused))
    life_canvas.pack() # boiler-plate: we always call pack() on tk windows

    # create blank rectangles for the entire grid
    rectangles = []
    for i in range(nx):
        rectangles.append([])
        for j in range(ny):
            r = life_canvas.create_rectangle(scale*i, scale*j, 
                                             scale*i+scale, scale*j+scale,
                                             fill='white')
            rectangles[i].append(r)


    board = setup_board(nx, ny)

    draw_rectangles(life_canvas, rectangles, board)
    life_canvas.update_idletasks()

    for i in range(1, n_steps):
        if not paused:
            board, changed_cells = apply_rule_to_board(board, rule_conway, 3, 3)
            # board, changed_cells = apply_rule_to_board(board, rule_snowflake, 3, 3)
            # draw_rectangles(life_canvas, rectangles, board)
            change_rectangles(life_canvas, rectangles, changed_cells, board)
            # life_canvas.update_idletasks()
            root.update()

    mainloop()



def setup_board(nx, ny):
    board = new_board(nx, ny)
    # set_initial_board_glider(board, int(nx/2), int(ny/2))
    # set_initial_board_random(board, 2)
    # set_initial_specific_cells(board, 2,
    #                            [(8, 13), (9, 13), (10, 13)])

    # set_initial_specific_cells(board, 2, [(int(nx/2), int(ny/2))])
    # set_initial_specific_cells(board, 2, [(int(nx/2)+1, int(ny/2))])
    # set_initial_specific_cells(board, 2, [(int(nx/2)+2, int(ny/2))])
    # set_initial_specific_cells(board, 2, [(int(nx/2), 1+int(ny/2))])
    # set_initial_specific_cells(board, 2, [(int(nx/2)+1, 1+int(ny/2))])
    # set_initial_specific_cells(board, 2, [(int(nx/2)+2, 1+int(ny/2))])
    # set_initial_board_glider(board, 40, 12)
    # set_initial_board_glider(board, 40, 30)
    # set_initial_board_lwss(board, 0, 60)
    # set_initial_board_lwss(board, 20, 60)
    # set_initial_board_lwss(board, 40, 60)
    # set_initial_board_lwss(board, 60, 60)
    # set_initial_board_lwss(board, 80, 60)
    # set_initial_board_lwss(board, 50, 10)
    # set_initial_board_one_cell_thick(board, 30, 30, True, 15)
    # set_initial_board_one_cell_thick(board, 31, 30, True, 15)

    ## Paul Callahan's initial pattern that gives infinite growth,
    ## see:
    ## http://www.conwaylife.com/w/index.php?title=One_cell_thick_pattern
    # set_initial_board_one_cell_thick(board, 10, 30, True, 8)
    # set_initial_board_one_cell_thick(board, 19, 30, True, 5)
    # set_initial_board_one_cell_thick(board, 28, 30, True, 3)
    # set_initial_board_one_cell_thick(board, 34, 30, True, 7)
    # set_initial_board_one_cell_thick(board, 42, 30, True, 5)

    ## http://www.conwaylife.com/w/index.php?title=One_cell_thick_pattern#cite_note-5
    ## one cell thick pattern which makes a glider
    set_initial_board_one_cell_thick(board, 10, 40, True, 4)
    set_initial_board_one_cell_thick(board, 16, 40, True, 3)
    set_initial_board_one_cell_thick(board, 20, 40, True, 5)
    return board

def mouse_press(evt, board, scale, paused):
    print('press', scale, paused)
    paused = True
    x = evt.x
    y = evt.y
    print('mouse position: %d, %d' % (x, y))
    board[int(x/scale)][int(y/scale)] = 1 - board[int(x/scale)][int(y/scale)]

def mouse_release(evt, board, scale, paused):
    print('release', scale, paused)
    paused = False
    x = evt.x
    y = evt.y
    print('mouse position: %d, %d' % (x, y))
    board[int(x/scale)][int(y/scale)] = 1 - board[int(x/scale)][int(y/scale)]

def draw_rectangles(canvas, rectangles, board):
    for i in range(len(board)):
        for j in range(len(board[i])):
            color = color_map[board[i][j]]
            canvas.itemconfig(rectangles[i][j], fill=color)

def change_rectangles(canvas, rectangles, changed_cells, board):
    """update the cells that have changed dynamically"""
    for (i, j) in changed_cells:
        color = color_map[board[i][j]]
        canvas.itemconfig(rectangles[i][j], fill=color)

main()
