# Simple code for MatrixPortal S3 with 32x32 RGB Matrix
import board
import displayio
import framebufferio
import rgbmatrix
import time
import analogio
import digitalio
import busio
import adafruit_lis3dh

# Set up the buttons
button_up = digitalio.DigitalInOut(board.BUTTON_UP)
button_up.direction = digitalio.Direction.INPUT
button_up.pull = digitalio.Pull.UP  # Buttons are active LOW

button_down = digitalio.DigitalInOut(board.BUTTON_DOWN)
button_down.direction = digitalio.Direction.INPUT
button_down.pull = digitalio.Pull.UP  # Buttons are active LOW

#Accelerometer Setup
i2c = busio.I2C(board.SCL, board.SDA)  # Use the default I2C pins
accelerometer = adafruit_lis3dh.LIS3DH_I2C(i2c, address=0x19)

#sensitivity
accelerometer.range = adafruit_lis3dh.RANGE_2_G

# Initialize the matrix
displayio.release_displays()
matrix = rgbmatrix.RGBMatrix(
    width=32, height=32,
    bit_depth=6,
    rgb_pins=[board.MTX_R1, board.MTX_G1, board.MTX_B1, board.MTX_R2, board.MTX_G2, board.MTX_B2],
    addr_pins=[board.MTX_ADDRA, board.MTX_ADDRB, board.MTX_ADDRC, board.MTX_ADDRD],
    clock_pin=board.MTX_CLK,
    latch_pin=board.MTX_LAT,
    output_enable_pin=board.MTX_OE,
)
display = framebufferio.FramebufferDisplay(matrix)

# Create a bitmap with 8 colors
bitmap = displayio.Bitmap(32, 32, 8)
palette = displayio.Palette(8)

# Define basic colors
palette[0] = 0x000000  # Black
palette[1] = 0xFF0000  # Red
palette[2] = 0x00FF00  # Green
palette[3] = 0x0000FF  # Blue
palette[4] = 0xFFFF00  # Yellow
palette[5] = 0xFF00FF  # Magenta
palette[6] = 0x00FFFF  # Cyan
palette[7] = 0xFFFFFF  # White


# Create the display elements
tile_grid = displayio.TileGrid(bitmap, pixel_shader=palette)
group = displayio.Group()
group.append(tile_grid)
display.root_group = group

# Set brightness
display.brightness = 1  # 100% brightness

# Function to set a pixel
def set_pixel(x, y, color):
    bitmap[x, y] = color


# First make everything black
for y in range(32):
    for x in range(32):
        bitmap[x, y] = 0  # Black (color index 0)

# Set just the middle pixel to white
bitmap[16, 16] = 7  # White (color index 7)

# Initializing variables
lit_up = [(16, 16)]  # Start with middle pixel already lit
x = 16
y = 16

sensitivity = 2

clr = [1,2,3,4,5,6,7]
clr_select = 6
last_x,last_y = 16,16



while True:
    if accelerometer.shake(shake_threshold = 12):
        print("shake")
        for y in range(32):
            for x in range(32):
                bitmap[x, y] = 0  # Black (color index 0)
        lit_up=[]
        x,y = last_x,last_y

    if not button_up.value:
        if clr_select == 6:
            clr_select = 0
        else:
            clr_select += 1

    if not button_down.value:
        if clr_select == 0:
            clr_select = 6
        else:
            clr_select -= 1

    x_acc, y_acc, z_acc = accelerometer.acceleration
    print(f"x: {x_acc:6.2f}, Y: {y_acc:6.2f}, Z: {z_acc:6.2f}")
    print(f"({x},{y})")

    if y_acc > sensitivity: #up
        y = min(31, y + 1)  # Prevent going off screen
    elif y_acc < -sensitivity: #down
        y = max(0, y - 1)  # Prevent going off screen
    elif x_acc > sensitivity: #right
        x = min(31, x + 1)  # Prevent going off screen (update x instead of y)
    elif x_acc < -sensitivity: #left
        x = max(0, x - 1)  # Prevent going off screen

    if x_acc < -sensitivity and y_acc < -sensitivity:  # Move diagonally down-left
        x = max(0, x - 1)
        y = max(0, y - 1)
    if x_acc > sensitivity and y_acc < -sensitivity:  # Move diagonally down-right
        x = min(31, x + 1)
        y = max(0, y - 1)
    if x_acc < -sensitivity and y_acc > sensitivity:  # Move diagonally up-left
        x = max(0, x - 1)
        y = min(31, y + 1)
    if x_acc > sensitivity and y_acc > sensitivity:  # Move diagonally up-right
        x = min(31, x + 1)
        y = min(31, y + 1)

    if (x, y) not in lit_up:
        lit_up.append((x, y))
        set_pixel(x, y, clr[clr_select])

    if (abs(max(x,y))) > sensitivity:
        time_sleep_adj = .005 * abs(max(x, y))
    else:
        time_sleep_adj = 0

    print(f"Time Sleep:{max(.1-time_sleep_adj,.0005)}")

    last_x,last_y = x,y
    time.sleep(max(.1-time_sleep_adj,.0005))
