import time
import board
import analogio
import digitalio
import neopixel
import wifi
import socketpool
import os
import ssl
import adafruit_minimqtt.adafruit_minimqtt as MQTT

# --- Config ---
NUM_PIXELS = 30
REDLINE_RPM = 9000
MAX_RPM = 11000
IDLE_RPM = 1000

# --- Hardware Setup ---
pot = analogio.AnalogIn(board.GP26)
button = digitalio.DigitalInOut(board.GP16)
button.direction = digitalio.Direction.INPUT
button.pull = digitalio.Pull.UP

pixels = neopixel.NeoPixel(board.GP2, NUM_PIXELS, brightness=0.4, auto_write=False)

# --- Wi-Fi and MQTT Setup --- 
print("Connecting to Wi-Fi...")
wifi.radio.connect(os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD"))
print("Connected to", os.getenv("CIRCUITPY_WIFI_SSID"))


# MQTT setup
pool = socketpool.SocketPool(wifi.radio)
aio_username = os.getenv("ADAFRUIT_AIO_USERNAME")
aio_key = os.getenv("ADAFRUIT_AIO_KEY")
broker = os.getenv("BROKER")
port = int(os.getenv("PORT"))
MQTT_FEED = aio_username + "/feeds/text_box"


mqtt_client = MQTT.MQTT(
    broker=broker,
    port=port,
    username=aio_username,
    password=aio_key,
    socket_pool=pool,
    ssl_context=ssl.create_default_context()
)

def connect(mqtt_client, userdata, flags, rc):
    print("Connected to MQTT broker!")

def disconnected(mqtt_client, userdata, rc):
    print("Disconnected from MQTT!")

def message(client, topic, message):
    print(f"New message on {topic}: {message}")

mqtt_client.on_connect = connect
mqtt_client.on_disconnect = disconnected
mqtt_client.on_message = message

print("Connecting to MQTT...")
mqtt_client.connect()

# --- Functions ---
def read_rpm():
    return int((pot.value / 65535) * (MAX_RPM - IDLE_RPM) + IDLE_RPM)

def get_color(rpm_percent):
    if rpm_percent < 0.5:
        return (0, int(255 * (rpm_percent * 2)), 0)
    else:
        return (int(255 * ((rpm_percent - 0.5) * 2)), int(255 * (1 - (rpm_percent - 0.5) * 2)), 0)

def update_strip(rpm):
    rpm_percent = min(rpm / MAX_RPM, 1.0)
    num_lit = int(rpm_percent * NUM_PIXELS)
    color = get_color(rpm_percent)

    for i in range(NUM_PIXELS):
        pixels[i] = color if i < num_lit else (0, 0, 0)
    pixels.show()

def redline_flash():
    for _ in range(3):
        for i in range(NUM_PIXELS):
            pixels[i] = (255, 0, 0)
        pixels.show()
        time.sleep(0.1)
        pixels.fill((0, 0, 0))
        pixels.show()
        time.sleep(0.1)

def startup_sweep():
    print("Startup sweep...")
    for i in range(NUM_PIXELS + 1):
        pixels.fill((0, 0, 0))
        for j in range(i):
            percent = j / NUM_PIXELS
            pixels[j] = get_color(percent)
        pixels.show()
        time.sleep(0.05)
    for i in reversed(range(NUM_PIXELS + 1)):
        pixels.fill((0, 0, 0))
        for j in range(i):
            percent = j / NUM_PIXELS
            pixels[j] = get_color(percent)
        pixels.show()
        time.sleep(0.05)

# --- Run Startup Animation ---
startup_sweep()

# --- Main Loop ---
last_post_time = 0
post_interval = 1.0

while True:
    mqtt_client.loop()

    rpm = read_rpm()
    engine_state = "ON" if not button.value else "OFF"

    if engine_state == "OFF":
        pixels.fill((0, 0, 0))
        pixels.show()
    elif rpm >= REDLINE_RPM:
        redline_flash()
    else:
        update_strip(rpm)

    now = time.monotonic()
    if now - last_post_time >= post_interval:
        msg = f"{rpm} RPM - {engine_state}"
        print("Publishing:", msg)
        mqtt_client.publish(MQTT_FEED, msg)
        last_post_time = now

    time.sleep(0.05)