import paho.mqtt.client as mqtt
from luma.core.interface.serial import i2c
from luma.oled.device import ssd1306
from PIL import Image, ImageDraw, ImageFont
import board
import neopixel_spi as neopixel
import time
import sys

# Configuration
MQTT_BROKER = "127.0.0.1"
MQTT_PORT = 1883
MQTT_TOPIC = "local"

# NeoPixel config
NUM_PIXELS = 24
pixels = neopixel.NeoPixel_SPI(board.SPI(), NUM_PIXELS, brightness=0.1, auto_write=False)

# State
lamp_on = False
current_color = (0, 0, 0)
last_palm_time = 0
PALM_COOLDOWN = 3  # seconds

# Color modes
MODE_COLORS = {
    "like": (0, 120, 255),     # Blue
    "dislike": (255, 50, 50),  # Red
    "vsign": (0, 255, 100)     # Green
}

# LED Helpers
def set_color(color_tuple):
    for i in range(NUM_PIXELS):
        pixels[i] = color_tuple
    pixels.show()

def fade_out(steps=30, delay_time=0.02):
    global current_color
    for s in range(steps + 1):
        r, g, b = current_color
        r_new = int(r * (1 - s / steps))
        g_new = int(g * (1 - s / steps))
        b_new = int(b * (1 - s / steps))
        for i in range(NUM_PIXELS):
            pixels[i] = (r_new, g_new, b_new)
        pixels.show()
        time.sleep(delay_time)
    pixels.fill((0, 0, 0))
    pixels.show()
    current_color = (0, 0, 0)

def transition_color(start_color, end_color, steps=30, delay=0.02):
    global current_color
    sr, sg, sb = start_color
    er, eg, eb = end_color
    for step in range(steps + 1):
        r = int(sr + (er - sr) * step / steps)
        g = int(sg + (eg - sg) * step / steps)
        b = int(sb + (eb - sb) * step / steps)
        for i in range(NUM_PIXELS):
            pixels[i] = (r, g, b)
        pixels.show()
        time.sleep(delay)
    current_color = end_color

# MQTT callbacks
def on_connect(client, userdata, flags, rc, properties=None):
    print(f"[MQTT] Connected with result code {rc}")
    client.subscribe(MQTT_TOPIC)
    print(f"[MQTT] Subscribed to topic: {MQTT_TOPIC}")

def on_message(client, userdata, msg):
    global lamp_on, current_color, last_palm_time

    payload = msg.payload.decode().strip()
    print(f"[MQTT] Message received on '{msg.topic}': {payload}")

    current_time = time.time()

    if payload == "palm":
        if current_time - last_palm_time < PALM_COOLDOWN:
            print("[INFO] Ignoring palm - in cooldown")
            return
        last_palm_time = current_time

        if lamp_on:
            print("[ACTION] Turning OFF lamp")
            fade_out()
            lamp_on = False
        else:
            print("[ACTION] Turning ON lamp (warm)")
            transition_color((0, 0, 0), (255, 200, 100))
            lamp_on = True

    elif payload in MODE_COLORS:
        if not lamp_on:
            print("[INFO] Lamp is OFF. Ignoring mode change.")
            return
        print(f"[ACTION] Setting mode: {payload}")
        transition_color(current_color, MODE_COLORS[payload])

    else:
        print(f"[WARNING] Unknown command: {payload}")

# Setup MQTT
client = mqtt.Client(client_id="rpi_listener", protocol=mqtt.MQTTv5)
client.on_connect = on_connect
client.on_message = on_message

client.connect(MQTT_BROKER, MQTT_PORT)

# Start MQTT loop and handle Ctrl+C
try:
    print("[INFO] Listening for messages... Press Ctrl+C to exit.")
    client.loop_forever()
except KeyboardInterrupt:
    print("\n[INFO] Shutting down gracefully...")
finally:
    fade_out()
    client.disconnect()
    print("[INFO] MQTT disconnected. LEDs off. Exit complete.")
    sys.exit(0)
