from PIL import Image
import random
import numpy as np  # jen kvůli data2img
import os           # jen kvůlli mazání dočasných souborů

periodicka_hranice = 1  # 0 nebo 1

def vyres_hranici(f):
    """
    Procedura v daném obdélníkovém poli vynuluje hranici
    případně zajístí periodicitu zkopírováním.
    Rozhoduje obsah proměnné

           periodicka_hranice = 0 nebo 1

    Argument:
        f ... Obdélníkové pole

    Vrací:
        Nic
    """
    for s in range(0,len(f[0])):
        f[0][s]   = f[-2][s]*periodicka_hranice
        f[-1][s]  = f[1][s]*periodicka_hranice

    for s in range(0,len(f)):
        f[s][0]   = f[s][-2]*periodicka_hranice
        f[s][-1]  = f[s][1]*periodicka_hranice


def step(f):
    """
    Procedura v daném obdélníkovém poli naplněném 0 nebo 1
    provede jeden krok Conwayova automatu Life

    Argument:
        f ... Obdélníkové pole

    Vrací:
        Nic
    """
    nr = len(f)
    nc = len(f[0])

    # nejprve musíme vytvořist stejně velké pole nul
    g  = [[0 for x in r] for r in f]

    for r in range(1, nr-1):
        for c in range(1, nc-1):
            s = f[r-1][c-1] + f[r-1][c] + f[r-1][c+1]   \
               +f[r  ][c-1]             + f[r  ][c+1]   \
               +f[r+1][c-1] + f[r+1][c] + f[r+1][c+1];

            if s == 3 or (f[r][c] == 1 and s == 2):
                g[r][c] = 1;

    if periodicka_hranice>0:
        vyres_hranici(g)
    return g


def rnd_data(size, p = 0.1 ):
    """ Vrací size x size pole 0 nebo 1 (p...pravděpodobnost 1) """
    data = [
                [ 1 if random.random() < p else 0 for k in range(size) ]
                for j in range(size)
           ]

    vyres_hranici( data )
    return data


def insert(kam, co, dx=0, dy=0):
    posun_r = (len(kam)-len(co)) // 2 - dy
    posun_s = (len(kam[0])-len(co[0])) // 2 + dx

    for r in range(0,len(co)):
        for s in range(0,len(co[0])):
            kam[posun_r+r][posun_s+s] = co[r][s]


glider = [[0,1,0],[0,0,1],[1,1,1]]

diehard = [[0, 0, 0, 0, 0, 0, 1, 0],
           [1, 1, 0, 0, 0, 0, 0, 0],
           [0, 1, 0, 0, 0, 1, 1, 1]]

acorn = [[0, 1, 0, 0, 0, 0, 0],
         [0, 0, 0, 1, 0, 0, 0],
         [1, 1, 0, 0, 1, 1, 1]]

pentax = [[0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
          [1, 1, 0, 1, 1, 1, 1, 0, 1, 1],
          [0, 0, 1, 0, 0, 0, 0, 1, 0, 0]]


# nemumím čitelněji konvertovat matici 0/1 na obrázek
def data2img(data):
    npdata = 255.0 - 255 * np.asarray(data,dtype=np.float32)
    npdata[::2,-1] = npdata[-1,::2] = npdata[::2,0] = npdata[0,::2] = 200
    return Image.fromarray(npdata).convert('L').resize( (360, 360) )


frames = []

data = rnd_data(130,p=0)    # p=0  => samá 0
insert(data, acorn, dy=10)

for i in range(400):
    frames.append( data2img( data ) )
    data = step( data )

# trik zobrazení animace v jupyteru
# náhodné názvy řeší kešování v prohlížeči
unique_prefix = 'animgwqh_'

# vadí-li kumulace velkých souborů, odkomentujte
#os.system('rm -f ' + unique_prefix + '*.gif')

rnd_file = unique_prefix+str(random.randrange(1000001,9000001))+'.gif'

# vytvoření animovaného gifu slitím frames[ ]
frames[0].save(rnd_file, format='GIF',
               append_images=frames[1:],
               save_all=True, duration=80, loop=0)

# vynucení zobrazní animace
from IPython.display import Image as inlineImg
from IPython.display import display
display( inlineImg(url=rnd_file)  )
