# -*- coding: utf-8 -*-
import copy
from random import randint
import time
import serial


WIDTH=6
HEIGHT=10
PIXELS=WIDTH*HEIGHT
FPS=3.0

#--RGB--object
class RGB:
    def __init__(self,red,green,blue):
        self.r=red
        self.g=green
        self.b=blue
    def setcolor(self,red,green,blue):
        self.r=red
        self.g=green
        self.b=blue
       
#--create--matrix
def new_m(w,h):#width/height    // returns 2 dimensional list
    matrix=[]         
    row=[]  
    for x in xrange(w):
        row.append(RGB(0,0,0))
    
    for y in xrange(h):
        matrix.append(copy.deepcopy(row))
    
    return matrix

#--print--matrix
def print_m(m):#matrix // 2 dimensional list
    h=len(m)
    w=len(m[0])
    for y in xrange(h):
        print y,"> |",
        for x in xrange(w):
            print x,"",m[y][x].r,m[y][x].g,m[y][x].b," |",
        print""


def img_to_m(path,m):  #path // matrix//width//height
    i = Image.open(path)
    pixels = i.load()

    h=len(m)
    w=len(m[0])    
    
    for x in range(w):
        for y in range(h):
            m[y][x].r,m[y][x].g,m[y][x].b = pixels[x, y]
 
          
          
def send_serial(ttyobj,m):#n=anzahl der pixel,m=matrix(liste)
	h=len(m)
	w=len(m[0])
	ttyobj.write(chr(1))#eine 1 pro anzahl aller pixel(hier 60)
	for x in xrange(w):			#layout der pixel:erst spalten, dann zeilen von oben rechts beginnend
		for y in xrange(h):
			
			tty.write(chr(m[y][w-1-x].r))
			tty.write(chr(m[y][w-1-x].g))
			tty.write(chr(m[y][w-1-x].b))    
            


def populate(c,m):	#anzahl der startzellen, matrix
	h=len(m)
	w=len(m[0])
	for y in xrange(h):			#alle pixel durchgehen
		for x in xrange(w):
			m[y][x].b=127
			m[y][x].r=127
	h=len(m)
	w=len(m[0])
	for i in xrange(c): #zufaelliges besetzen
		y=randint(0,h-1)
		x=randint(0,w-1)
		m[y][x].setcolor(255,0,0)
	return m 


def isPopulated(m,y,x,yBorder,xBorder):
	if 0 <= y < yBorder:
		if 0 <= x < xBorder:
			if m[y][x].r==255: #schwellwert fuer lebende zelle
				return True
	else:
		return False

		
def checkNeighbours(m,y,x):
	h=len(m)
	w=len(m[0])	
	c=0
	if isPopulated(m,y-1,x-1,h,w):
		c=c+1
	if isPopulated(m,y-1,x,h,w):
		c=c+1	
	if isPopulated(m,y-1,x+1,h,w):
		c=c+1
		
		
	if isPopulated(m,y,x-1,h,w):
		c=c+1
	if isPopulated(m,y,x+1,h,w):
		c=c+1
		
		
	if isPopulated(m,y+1,x-1,h,w):
		c=c+1
	if isPopulated(m,y+1,x,h,w):
		c=c+1
	if isPopulated(m,y+1,x+1,h,w):
		c=c+1		
	return c
		
		
		
def nextGen(f,m): #frame, matrix
	equalPixels=0
	h=len(m)
	w=len(m[0])
	bufferMatrix=new_m(w,h)
	for y in xrange(h):			#alle pixel durchgehen
		for x in xrange(w):
			n=checkNeighbours(m,y,x)
			if n<2 or n>3:
				bufferMatrix[y][x].b=127
				bufferMatrix[y][x].r=m[y][x].r/2
			elif m[y][x].r<255 and n==3:
				bufferMatrix[y][x].r=255
			elif m[y][x].r==255 and 2<=n<=3:
				bufferMatrix[y][x].r=255
			else:
				bufferMatrix[y][x].b=127
				bufferMatrix[y][x].r=m[y][x].r/2
			
			if bufferMatrix[y][x].r==m[y][x].r:
				equalPixels=equalPixels+1
	if equalPixels==h*w:
		return populate(randint(0,60),new_m(WIDTH,HEIGHT))
	return bufferMatrix #returns processed image
               


#MAINLOOP

running=True
frame=0
target_delta=1/FPS

print "creating matrix..."
matrix=new_m(WIDTH,HEIGHT)

print "populating..."
matrix=populate(40,matrix)
print_m(matrix)
print "opening serial port..."
tty=serial.Serial("/dev/ttyACM3", 500000)
time.sleep(1)


send_serial(tty,matrix)
time.sleep(target_delta)

while running:
    time_a=time.time()
    matrix=nextGen(frame,matrix)
    #print_m(matrix)
        
    time_b=time.time()

    
    time.sleep(target_delta-(time_b-time_a))

    send_serial(tty,matrix)
    print 1/(time.time()-time_a)
    frame=frame+1
