import sys
import time
import RPi.GPIO as GPIO
from PIL import Image
from rgbmatrix import RGBMatrix, RGBMatrixOptions
import glob
import numpy as np
from PIL import Image

# GPIO Configuration
BUTTON_PIN = 25     # User button to start first image
TRIGGER_PIN = 18    # Signal to advance to next image
SIGNAL_PIN = 19     # Output signal when image updates

GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(TRIGGER_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(SIGNAL_PIN, GPIO.OUT)
GPIO.output(SIGNAL_PIN, GPIO.LOW)

# Configure the LED matrix options
options = RGBMatrixOptions()
options.rows = 64
options.cols = 64
options.chain_length = 1
options.parallel = 1
options.hardware_mapping = 'adafruit-hat'  # For Adafruit Bonnet
options.brightness = 100
options.gpio_slowdown = 4
options.pwm_lsb_nanoseconds = 130
options.pwm_bits = 11

matrix = RGBMatrix(options=options)

# Load all stripe images in numerical order
# image_files = sorted(glob.glob("patterns/pixels/32pixels/square4_*.png"))
# image_files = sorted(glob.glob("patterns/hadamard/32x32_padded/hadamardPadded_*.png"))
# image_files = sorted(glob.glob("patterns/test2/test_*.png"))
image_files = sorted(glob.glob("patterns/hadamard/64x64/hadamard_*.png"))
# image_files = sorted(glob.glob("patterns/pixels/64pixels/square4_*.png"))
black_image = Image.new("RGB",(64,64),(0,0,0))

# Load images into memory
images = []
for img_path in image_files:
    image = Image.open(img_path).convert('RGB').resize((64, 64))
    r, g, b = image.split()
    images.append(Image.merge("RGB", (b, g, r)))

current_image = 0

def display_image():
    """Displays the current image and pulses SIGNAL_PIN (Pin 19)."""
    matrix.SetImage(black_image)
    time.sleep(0.06)  # 2ms high signal
    matrix.SetImage(images[current_image])
    time.sleep(0.07)  # 2ms high signal
    GPIO.output(SIGNAL_PIN, GPIO.HIGH)
    time.sleep(0.002)  # 2ms high signal
    GPIO.output(SIGNAL_PIN, GPIO.LOW)
    # time.sleep(0.02)  # 2ms high signal

# Wait for the button press to display the first image
print("Press the button to start.")
GPIO.wait_for_edge(BUTTON_PIN, GPIO.RISING)
time.sleep(0.015)  # 2ms high signal
display_image()

# Function to handle next image display on rising edge of TRIGGER_PIN (Pin 18)
def trigger_callback(channel):
    global current_image
    current_image = (current_image + 1) % len(images)  # Loop through images
    display_image()
    
GPIO.setup(TRIGGER_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

# Add event detection for next image trigger
GPIO.add_event_detect(TRIGGER_PIN, GPIO.RISING, callback=trigger_callback, bouncetime=500)

try:
    while True:
        time.sleep(0.1)  # Keep running and waiting for trigger signal
finally:
    print("Exiting gracefully.")
    GPIO.cleanup()
