import socket
import threading
import time
from RPi import GPIO
from lcd import LCD
from rgb_led import RGB_LED

# Global vars for use in methods/threads
client_socket = None
server_socket = None
server_thread = None
shutdown_flag = threading.Event()  # see: https://docs.python.org/3/library/threading.html#event-objects

# GPIO setup
BUTTON_PIN = 21
RGB_LED_RED_PIN = 5
RGB_LED_GREEN_PIN = 6
RGB_LED_BLUE_PIN = 13

# Initialize the RGB LED and LCD
rgb_led = RGB_LED(RGB_LED_RED_PIN, RGB_LED_GREEN_PIN, RGB_LED_BLUE_PIN)
lcd = LCD(0x27)
lcd.init_LCD()

led_on = True  # Variable to track the LED state

def button_callback(channel):
    global led_on
    led_on = not led_on
    if not led_on:
        rgb_led.turn_off()
    print(f"Button pressed, LED state is now {'on' if led_on else 'off'}")

def setup_GPIO():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    GPIO.add_event_detect(BUTTON_PIN, GPIO.FALLING, callback=button_callback, bouncetime=200)

def setup_socket_server():
    global server_socket, server_thread, shutdown_flag
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(('0.0.0.0', 8500))
    server_socket.settimeout(0.2)
    server_socket.listen(1)

    server_thread = threading.Thread(target=accept_connections, args=(shutdown_flag,), daemon=True)
    server_thread.start()

def accept_connections(shutdown_flag):
    global client_socket
    print("Accepting connections")
    while not shutdown_flag.is_set():
        try:
            client_socket, addr = server_socket.accept()
            print("Connected by", addr)
            client_thread = threading.Thread(target=handle_client, args=(client_socket, shutdown_flag,))
            client_thread.start()
        except socket.timeout:
            pass

def handle_client(sock, shutdown_flag):
    try:
        while not shutdown_flag.is_set():
            data = sock.recv(1024)
            if not data:
                break
            message = data.decode()
            print("Received from client:", message)
            if message.strip() == "":
                continue
            message_parts = message.split(", ")
            if len(message_parts) != 2:
                print("Invalid message format")
                continue
            emotion, accuracy = message_parts
            lcd.clear_display()
            lcd.send_string(emotion, 1)
            lcd.send_string(accuracy, 2)
            if led_on:
                if emotion == 'happy dog':
                    rgb_led.set_color('green')
                elif emotion == 'angry dog':
                    rgb_led.set_color('red')
                elif emotion == 'sad dog':
                    rgb_led.set_color('blue')
                elif emotion == 'neutral dog':
                    rgb_led.set_color('white')
    except socket.timeout:
        pass
    except Exception as e:
        print(f"Error: {e}")
    finally:
        sock.close()

try:
    setup_GPIO()
    setup_socket_server()
    while True:
        time.sleep(10)
        if client_socket:
            try:
                client_socket.sendall("Hello from RPi loop".encode())
            except Exception as e:
                print(f"Failed to send message: {e}")

except KeyboardInterrupt:
    print("Server shutting down")
    shutdown_flag.set()
    lcd.clear_display()  # Clear the LCD display before shutting down
finally:
    server_thread.join()
    server_socket.close()
    rgb_led.cleanup()
    GPIO.cleanup()
