import tkinter as tk
from tkinter import Label, Frame
from tkinter import Label, Frame, messagebox
from tkinter import ttk
from PIL import Image, ImageTk  # type: ignore
import subprocess
import os
import sys
import re
from pyq3serverlist import Server

# ================= CONFIGURATION =================
SERVER_IP = "96.126.107.177"
SERVER_PORT = 27200

# PASTE YOUR FOLDER PATH BELOW inside the quotes r"..."
IMAGE_FOLDER = r"G:\programming\src\adv-oamonitor\map_screenshots" 

GAME_EXE_PATH = r"C:\Games\omega_full\OmegA\omega-vulkan.x64.exe"
DEFAULT_IMAGE_SIZE = (400, 300)

GAMETYPES = {
    0: "Free For All",
    1: "Tournament",
    3: "Team Deathmatch",
    4: "Capture The Flag",
    5: "One Flag CTF",
    6: "Obelisk",
    7: "Harvester",
    8: "Elimination",
    9: "CTF Elimination",
    10: "Last Man Standing",
    11: "Double Domination",
    12: "Domination"
}
# =================================================

def strip_colors(text):
    """Removes Quake 3 color codes (e.g. ^1, ^7) from text."""
    return re.sub(r'\^[0-9]', '', text)

def get_server_data():
    server = Server(SERVER_IP, SERVER_PORT)
    try:
        status = server.get_status()
        
        # --- GAME TYPE ---
        raw_type = status.get('g_gametype') or status.get('gametype', '0')
        try:
            type_id = int(raw_type)
            gametype_str = GAMETYPES.get(type_id, f"Unknown ({type_id})")
        except:
            gametype_str = "Unknown"

        # --- SERVER NAME ---
        raw_name = status.get('sv_hostname', 'OpenArena Server')
        clean_name = strip_colors(raw_name)

        return {
            "success": True,
            "servername": clean_name,
            "mapname": status.get('mapname', 'Unknown'),
            "gametype": gametype_str,
            "players": status.get('players', []),
            "num_players": len(status.get('players', [])),
            "max_players": status.get('maxplayers', '16')
        }
    except Exception as e:
        return {"success": False, "error": str(e)}

def load_map_image(map_name):
    extensions = [".jpg", ".png", ".jpeg", ".tga"]
    image_path = None

    if not os.path.exists(IMAGE_FOLDER):
        img = Image.new('RGB', DEFAULT_IMAGE_SIZE, color=(73, 73, 73))
        img = img.resize(DEFAULT_IMAGE_SIZE, Image.Resampling.LANCZOS)
        return ImageTk.PhotoImage(img)

    for ext in extensions:
        potential_path = os.path.join(IMAGE_FOLDER, f"{map_name}{ext}")
        if os.path.exists(potential_path):
            image_path = potential_path
            break
    
    if not image_path:
        img = Image.new('RGB', DEFAULT_IMAGE_SIZE, color=(73, 73, 73))
    else:
        try:
            img = Image.open(image_path)
        except:
            img = Image.new('RGB', DEFAULT_IMAGE_SIZE, color=(255, 100, 100))

    img = img.resize(DEFAULT_IMAGE_SIZE, Image.Resampling.LANCZOS)
    return ImageTk.PhotoImage(img)

def launch_game():
    if not os.path.exists(GAME_EXE_PATH):
        messagebox.showerror("Error", f"Game executable not found at:\n{GAME_EXE_PATH}")
        return
    
    cmd = [GAME_EXE_PATH, "+connect", f"{SERVER_IP}:{SERVER_PORT}"]
    subprocess.Popen(cmd, cwd=os.path.dirname(GAME_EXE_PATH))

# --- NEW FUNCTION: Handles clearing and rebuilding the UI content ---
def refresh_content(root, content_frame):
    # 1. Clear previous content (widgets) from the frame
    for widget in content_frame.winfo_children():
        widget.destroy()

    # 2. Update Title to show we are working
    root.title("Refreshing...")
    root.update_idletasks()

    # 3. Fetch Data
    data = get_server_data()
    
    # 4. Update Window Title with Server Name
    window_title = data['servername'] if data["success"] else f"Server: {SERVER_IP}"
    root.title(window_title)

    # 5. Build Image
    map_name = data.get("mapname", "unknown") if data["success"] else "error"
    photo = load_map_image(map_name)

    img_label = Label(content_frame, image=photo, bg="#2b2b2b")
    img_label.image = photo  # Keep reference so it doesn't disappear!
    img_label.pack(pady=10, padx=10)

    # 6. Build Info Text
    info_subframe = Frame(content_frame, bg="#2b2b2b")
    info_subframe.pack(fill="both", expand=True, padx=10, pady=(0, 10))

    if data["success"]:
        header_text = (f"Server: {data['servername']}\n"
                       f"Map:    {data['mapname']}\n"
                       f"Mode:   {data['gametype']}\n"
                       f"Players: {data['num_players']}/{data['max_players']}")
        
        Label(info_subframe, text=header_text, font=("Helvetica", 12, "bold"), fg="white", bg="#2b2b2b", justify="left").pack(anchor="w")
        
        if data['num_players'] > 0:
            Label(info_subframe, text="\nOnline Players:", font=("Helvetica", 10, "bold"), fg="#aaaaaa", bg="#2b2b2b").pack(anchor="w")
            for p in data['players']:
                clean_p_name = strip_colors(p.get('name', 'Unknown'))
                score = p.get('frags', p.get('score', 0))
                p_text = f"• [{score}] {clean_p_name} ({p.get('ping', '--')}ms)"
                
                # Ping Color Logic
                try:
                    ping_val = int(p.get('ping', 999))
                except:
                    ping_val = 999
                
                ping_color = "#55ff55" if ping_val < 60 else "#ffff55" if ping_val < 120 else "#ff5555"
                
                Label(info_subframe, text=p_text, font=("Consolas", 10), fg=ping_color, bg="#2b2b2b").pack(anchor="w")
        else:
            Label(info_subframe, text="\nServer is empty.", font=("Helvetica", 10, "italic"), fg="#aaaaaa", bg="#2b2b2b").pack(anchor="w")
    else:
        Label(info_subframe, text="Connection Error", font=("Helvetica", 12, "bold"), fg="#ff5555", bg="#2b2b2b").pack()
        Label(info_subframe, text=data.get("error", "Unknown"), wraplength=380, fg="white", bg="#2b2b2b").pack()

def build_gui():
    root = tk.Tk()
    root.configure(bg="#2b2b2b")
    # Title is set inside refresh_content

    # 1. Content Frame (Holds Image + Stats)
    content_frame = Frame(root, bg="#2b2b2b")
    content_frame.pack(fill="both", expand=True)

    # 2. Button Frame (Holds Refresh + Close)
    button_frame = Frame(root, bg="#2b2b2b")
    button_frame.pack(fill="x", pady=10)

    # --- BUTTONS ---
    # Refresh Button: Calls refresh_content passing the root and the content frame
    btn_refresh = tk.Button(button_frame, text="Refresh", 
                            command=lambda: refresh_content(root, content_frame),
                            bg="#007acc", fg="white", width=12) # Blue button
    btn_refresh.pack(side="left", padx=20)

    # Auto-Refresh Checkbox
    auto_refresh_var = tk.BooleanVar()
    refresh_interval_var = tk.StringVar(value="5")

    def auto_refresh_loop():
        if auto_refresh_var.get():
            refresh_content(root, content_frame)
            try:
                interval = int(refresh_interval_var.get()) * 1000
            except:
                interval = 5000
            root.after(interval, auto_refresh_loop)

    chk_auto = tk.Checkbutton(button_frame, text="Auto:", variable=auto_refresh_var, 
                              command=auto_refresh_loop, bg="#2b2b2b", fg="white", selectcolor="#444", activebackground="#2b2b2b", activeforeground="white")
    chk_auto.pack(side="left", padx=(10, 2))

    combo_interval = ttk.Combobox(button_frame, textvariable=refresh_interval_var, values=["5", "10", "30", "60", "120"], width=4, state="readonly")
    combo_interval.pack(side="left")
    
    Label(button_frame, text="s", bg="#2b2b2b", fg="white").pack(side="left", padx=(0, 10))

    # Connect Button
    btn_connect = tk.Button(button_frame, text="Connect", 
                            command=launch_game,
                            bg="#28a745", fg="white", width=12)
    btn_connect.pack(side="left", padx=20)

    # Close Button
    btn_close = tk.Button(button_frame, text="Close", 
                          command=root.destroy, 
                          bg="#444", fg="white", width=12)
    btn_close.pack(side="right", padx=20)

    # 3. Initial Load
    refresh_content(root, content_frame)

    # 4. Center Window
    root.update_idletasks()
    width = max(root.winfo_width(), 460)
    height = max(root.winfo_height(), 780)
    x = (root.winfo_screenwidth() // 2) - (width // 2)
    y = (root.winfo_screenheight() // 2) - (height // 2)
    root.geometry(f'{width}x{height}+{x}+{y}')

    root.mainloop()

if __name__ == "__main__":
    build_gui()