import time
from machine import Pin
from neopixel import NeoPixel
from random import choice, randint

# Attach 25 Neopixel LEDs to GPIO 16
np = NeoPixel(Pin(16), 25, bpp = 3)

#Set pixel color at x,y to r,g,b
#If write==True, flush the buffer
def setPixel(x,y,r,g,b,write=True):
    np[5 * x + y] = (r,g,b)
    if(write):
        np.write()

#Groups of pixels with the same color
pixel_groups=[[[0,0],[4,0],[0,4],[4,4]],\
              [[1,1],[3,1],[1,3],[3,3]],\
              [[2,2]],\
              [[2,0],[0,2],[4,2],[2,4]],\
              [[2,1],[1,2],[3,2],[2,3]],\
              [[0,1],[0,3],[1,0],[1,4],[3,0],[3,4],[4,1],[4,3]]]

#Color palettes
palettes = [[[0,0,0],[32,22,0],[0,22,16]],\
            [[0,0,0],[5,10,32],[4,32,2]],\
            [[0,0,0],[12,44,0],[48,6,2]],\
            [[0,0,0],[32,24,0],[32,0,0]]]

#Colors of each group of pixels
group_colors=[[0,0,0]]*len(pixel_groups)

#Smooth color transition
#shades argument indicates the number of transition shades 
def morph_colors(group,old_color,new_color, shades=16):
    #Calculate the difference between new and old color
    color_difference = [color2-color1 for color1,color2 in zip(old_color,new_color)]
    for i in range(shades):
        for pixel in group:
            setPixel(pixel[0],pixel[1],\
                     old_color[0]+color_difference[0]*i//shades,\
                     old_color[1]+color_difference[1]*i//shades,\
                     old_color[2]+color_difference[2]*i//shades,\
                     write=False)
        np.write() #flush the buffer
        time.sleep(0.01) #animation speed
        for pixel in group:
            setPixel(pixel[0],pixel[1],new_color[0],new_color[1],new_color[2])

#Clear matrix
np.fill((0,0,0))
np.write()

#Main loop
while(True):
    palette = choice(palettes) #pick a random palette
    #Display some animation with the selected palette
    for i in range(50):
        group_number = randint(0,len(pixel_groups)-1) #pick a random group of pixels
        color = choice(palette) #pick a random color from the palette
        morph_colors(pixel_groups[group_number], group_colors[group_number], color) #change the group color
        group_colors[group_number] = color