from color import Color
import math
import bhi160
import display
import utime
import urandom
import buttons

disp = display.open()

particle_size = 5
width = int(160 / particle_size)
height = int(80 / particle_size)
num_particles = 250 / particle_size
bounce_factor = 0.3

accelerometer = bhi160.BHI160Accelerometer()
particles = []

grid = [[False for i in range(height)] for j in range(width)]

class Particle:
    def __init__(self, loc):
        global grid
        self.col = Color.from_hsv(urandom.randrange(0,365), 0.75, 1.0)
        self.loc = list(float(i) for i in loc)
        self.v = [0.0, 0.0]
        grid[loc[0]][loc[1]] = True

    def draw(self):
        disp.rect(int(self.loc[0]*particle_size), int(self.loc[1]*particle_size), int(self.loc[0]*particle_size + (particle_size-1)), int(self.loc[1]*particle_size + (particle_size-1)), col=self.col)

    def update(self, a):
        self.v[0] += a.x
        self.v[1] -= a.y # y axis reversed

    def move(self):
        if self.v[0] > 0 and occupied([self.loc[0]+1, self.loc[1]]):
            if occupied([self.loc[0]-1, self.loc[1]]):
                self.v[0] = 0
            else:
                self.v[0] *= -bounce_factor

            return

        if self.v[0] < 0 and occupied([self.loc[0]-1, self.loc[1]]):
            if occupied([self.loc[0]+1, self.loc[1]]):
                self.v[0] = 0
            else:
                self.v[0] *= -bounce_factor
            return

        if self.v[1] > 0 and occupied([self.loc[0], self.loc[1]+1]):
            if occupied([self.loc[1], self.loc[1]-1]):
                self.v[1] = 0
            else:
                self.v[1] *= -bounce_factor

            return

        if self.v[1] < 0 and occupied([self.loc[0], self.loc[1]-1]):
            if occupied([self.loc[1], self.loc[1]+1]):
                self.v[1] = 0
            else:
                self.v[1] *= -bounce_factor

            return

        grid[int(self.loc[0])][int(self.loc[1])] = False

        self.loc[0] += self.v[0]
        self.loc[1] += self.v[1]

        if self.loc[0] > width-1:
            self.loc[0] = float(width-1)

        if self.loc[0] < 0:
            self.loc[0] = 0

        if self.loc[1] > height-1:
            self.loc[1] = float(height-1)

        if self.loc[1] < 0:
            self.loc[1] = 0

        grid[int(self.loc[0])][int(self.loc[1])] = True

        # self.col[1] / 2
        # self.col[1] += (math.fabs(self.v[0]) + math.fabs(self.v[1]))/4
        # if self.col[1] < 0.25:
            # self.col[1] = 0.25

def occupied(loc):
    if loc[0] < 0 or loc[0] >= width:
        return True

    if loc[1] < 0 or loc[1] >= height:
        return True

    return grid[int(loc[0])][int(loc[1])]

for i in range(num_particles):
    loc = [urandom.randrange(0,width), urandom.randrange(0,height)]

    while occupied(loc):
        loc = [urandom.randrange(0,width), urandom.randrange(0,height)]

    particles.append(Particle(loc))

counter = 0

disp.clear([0,0,0])
disp.print("<-bounce+>", posx=10, posy=60, fg=[0,255,255])
disp.update()
utime.sleep(3)

while True:
    if counter % 4 == 0:
        samples = accelerometer.read()

    if len(samples) > 0:
        disp.clear()

        for part in particles:
            if counter % 4 == 0:
                part.update(samples[0])

            part.move()
            part.draw()

        disp.line(0, 79, int(160*bounce_factor), 79, col=[0,255,255])
        disp.update()

    counter += 1

    v = buttons.read(buttons.BOTTOM_LEFT)

    if v == 0:
        l_button_pressed = False

    if not l_button_pressed and v & buttons.BOTTOM_LEFT != 0:
        l_button_pressed = True
        bounce_factor -= 0.1
        if bounce_factor < 0.0:
            bounce_factor = 0.0

    v = buttons.read(buttons.BOTTOM_RIGHT)

    if v == 0:
        r_button_pressed = False

    if not r_button_pressed and v & buttons.BOTTOM_RIGHT != 0:
        r_button_pressed = True
        bounce_factor += 0.1
        if bounce_factor > 1.0:
            bounce_factor = 1.0
