import serial
import pyautogui
import time

# Configuration for ESP32 connection
ESP32_PORT = "COM14"  # Replace with your ESP32 COM port
BAUD_RATE = 115200

# Coordinates for each option (A, B, C, D) for both players
OPTIONS_COORDS_PLAYER_1 = [
    (482, 500),  # Option A
    (782, 489),  # Option B
    (1106, 483), # Option C
    (1409, 482)  # Option D
]

OPTIONS_COORDS_PLAYER_2 = [
    (482, 600),  # Option A
    (782, 589),  # Option B
    (1106, 583), # Option C
    (1409, 582)  # Option D
]

# Timing thresholds to prevent accidental keypresses
KEY_PRESS_DELAY = 1  # Seconds

# Initialize tracking variables for both players
player_data = {
    '1': {
        'current_option_index': 0,
        'last_left_press_time': 0,
        'last_right_press_time': 0,
        'last_enter_press_time': 0,
        'options_coords': OPTIONS_COORDS_PLAYER_1
    },
    '2': {
        'current_option_index': 0,
        'last_left_press_time': 0,
        'last_right_press_time': 0,
        'last_enter_press_time': 0,
        'options_coords': OPTIONS_COORDS_PLAYER_2
    }
}

def connect_to_esp32(port, baud_rate):
    """Establish a serial connection to the ESP32."""
    try:
        ser = serial.Serial(port, baud_rate)
        print(f"Connected to ESP32 on {port} at {baud_rate} baud.")
        return ser
    except Exception as e:
        print(f"Error connecting to ESP32: {e}")
        exit()

def move_mouse_to_option(player_id):
    """Smoothly move the mouse to the specified option's coordinates for the given player."""
    player = player_data[player_id]
    x, y = player['options_coords'][player['current_option_index']]
    pyautogui.moveTo(x, y, duration=0.2)

def handle_keypress(player_id, x, y, z):
    """
    Handle simulated keypress events based on x, y, z values.
    This controls mouse movement and option selection for the given player.
    """
    player = player_data[player_id]
    current_time = time.time()

    # Handle left arrow key (select previous option)
    if z > 370 and x < 300 and (current_time - player['last_left_press_time'] > KEY_PRESS_DELAY):
        player['current_option_index'] = (player['current_option_index'] - 1) % len(player['options_coords'])  # Cycle backwards
        print(f"Player {player_id} Selected Option: {chr(65 + player['current_option_index'])}")  # A, B, C, D
        move_mouse_to_option(player_id)
        player['last_left_press_time'] = current_time

    # Handle right arrow key (select next option)
    if z < -200 and x < 300 and (current_time - player['last_right_press_time'] > KEY_PRESS_DELAY):
        player['current_option_index'] = (player['current_option_index'] + 1) % len(player['options_coords'])  # Cycle forwards
        print(f"Player {player_id} Selected Option: {chr(65 + player['current_option_index'])}")  # A, B, C, D
        move_mouse_to_option(player_id)
        player['last_right_press_time'] = current_time

    # Handle enter key (click on current option)
    if y > 350 and (current_time - player['last_enter_press_time'] > KEY_PRESS_DELAY):
        print(f"Player {player_id} Clicked on Option: {chr(65 + player['current_option_index'])}")
        pyautogui.click()  # Simulate mouse click
        player['last_enter_press_time'] = current_time

def main():
    """Main program loop to read data from ESP32 and handle input."""
    # Connect to ESP32
    ser = connect_to_esp32(ESP32_PORT, BAUD_RATE)

    try:
        # Move mouse to the initial option for both players
        move_mouse_to_option('1')
        move_mouse_to_option('2')

        while True:
            # Check if data is available from the ESP32
            if ser.in_waiting > 0:
                # Read and decode a line of data
                data = ser.readline().decode('utf-8').strip()

                try:
                    # Parse player ID and x, y, z values from the received data
                    player_id, values = data.split(':')
                    x, y, z = map(int, values.split(','))

                    # Process the keypress for the corresponding player
                    if player_id in player_data:
                        handle_keypress(player_id, x, y, z)
                except ValueError:
                    print(f"Invalid data received: {data}")

    except KeyboardInterrupt:
        print("Program terminated by user.")
    finally:
        # Close the serial connection
        ser.close()
        print("Serial connection closed.")

# Run the program
if __name__ == "__main__":
    main()
