import pytchat
import socket
import json
import time
import sys
import re

# Configuration
GODOT_IP = "127.0.0.1"
GODOT_PORT = 5555
PYTHON_PORT = 5556

def extract_video_id(user_input):
    """Extracts ID from a full URL or returns the ID if already clean."""
    # Regex to find the 11-character YouTube ID
    regex = r"(?:v=|\/)([0-9A-Za-z_-]{11}).*"
    match = re.search(regex, user_input)
    if match:
        return match.group(1)
    return user_input.strip()

def start_bridge():
    # Setup UDP Socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind(("0.0.0.0", PYTHON_PORT))
    sock.settimeout(1.0)

    print("\n\nYOUTUBE TO GODOT BRIDGE")

    # PROMPT USER FOR VIDEO ID
    raw_input = input("Paste YouTube Video ID or full URL: ").strip()
    video_id = extract_video_id(raw_input)

    if len(video_id) != 11:
        print(f"Error: '{video_id}' does not look like a valid YouTube ID.")
        input("Press Enter to exit...")
        return

    # 1. HANDSHAKE PHASE
    connected = False
    ping_payload = json.dumps({"type": "ping"}).encode('utf-8')

    print(f"\nTargeting: {video_id}")
    print(f"Waiting for Godot on port {GODOT_PORT}...")

    while not connected:
        try:
            sock.sendto(ping_payload, (GODOT_IP, GODOT_PORT))
            data, addr = sock.recvfrom(1024)
            if json.loads(data.decode('utf-8')).get("type") == "pong":
                print(">> Connected to Godot!")
                connected = True
        except (socket.timeout, json.JSONDecodeError):
            print(".", end="", flush=True) # Loading dots
            time.sleep(1)

    # 2. CHAT FORWARDING PHASE
    try:
        chat = pytchat.create(video_id=video_id)
        print(f"\nStatus: Monitoring YouTube chat...\n")

        while chat.is_alive():
            for c in chat.get().sync_items():
                payload = {
                    "type": "youtube_chat",
                    "user": c.author.name,
                    "message": c.message,
                    "pfp": c.author.imageUrl
                }
                sock.sendto(json.dumps(payload, ensure_ascii=False).encode('utf-8'), (GODOT_IP, GODOT_PORT))
                print(f"[SENT] {c.author.name}: {c.message}")
            time.sleep(0.1)
    except Exception as e:
        print(f"\nAn error occurred: {e}")
    finally:
        sock.close()
        print("\nBridge closed.")

if __name__ == "__main__":
    start_bridge()
