"""
flyffbot.py [instance_name] — launch ONE self-contained Flyff bot instance:
a headed Chromium with its OWN profile (so each instance logs into its own
account/char), the in-game control panel, and the bot supervisor.

Run several at once with different names for multiple accounts in parallel —
each gets its own window, its own login, and its own auto-assigned debug port,
and the bots don't fight over the mouse (input goes to each window separately).

  python flyffbot.py            -> instance "main"   (profile ./profiles/main)
  python flyffbot.py farmer2    -> instance "farmer2" (a second login window)

Usually launched via flyffbot.bat. Log into the desired account in the window
that opens, then use the panel buttons (Grind selected / local / aibat).
"""
import sys
import socket
from pathlib import Path
from playwright.sync_api import sync_playwright
import control
import license_check   # license gate (no-op in the dev copy via the LICENSE_DEV marker)

FLYFF_URL = "https://universe.flyff.com/play"


def free_port(start=9222):
    for port in range(start, start + 100):
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            if s.connect_ex(("127.0.0.1", port)) != 0:
                return port
    return start


def instance_name(explicit, port):
    """Pick the profile name. An explicit arg always wins. With no arg we reuse
    'main' only when the base debug port is free (no other instance running);
    otherwise we auto-pick a unique name so a second launch doesn't collide with
    the first window's profile — Chromium can't share one user-data-dir, and trying
    to just hands the launch off to the existing window and exits."""
    if explicit:
        return explicit
    idx = port - 9222                       # 0 = first instance, 1 = second, …
    return "main" if idx <= 0 else f"main{idx + 1}"


def main():
    license_check.require()                 # exits with a message if the license is missing/revoked
    explicit = sys.argv[1] if len(sys.argv) > 1 else None
    port = free_port()
    name = instance_name(explicit, port)
    profile = Path(__file__).parent / "profiles" / name
    profile.mkdir(parents=True, exist_ok=True)
    print(f"[{name}] starting — profile ./profiles/{name}, debug port {port}")
    with sync_playwright() as p:
        try:
            ctx = p.chromium.launch_persistent_context(
                user_data_dir=str(profile),
                headless=False,
                no_viewport=True,
                args=[f"--remote-debugging-port={port}", "--start-maximized"],
            )
        except Exception as e:
            print(f"\n[{name}] Could not launch the browser.")
            print(f"The profile ./profiles/{name} is most likely already open in another")
            print( "flyffbot window — Chromium can't run two windows on the same profile.")
            print( "Start this extra instance under its own name, e.g.:\n")
            print( "    flyffbot.bat farmer2\n")
            print(f"(original error: {type(e).__name__}: {str(e).splitlines()[0]})")
            return
        page = ctx.pages[0] if ctx.pages else ctx.new_page()
        try:
            page.goto(FLYFF_URL, wait_until="domcontentloaded")
        except Exception as e:
            print(f"(nav note: {e}) — navigate to the game manually if needed.")
        size = page.evaluate("({w: window.innerWidth, h: window.innerHeight})")
        print(f"[{name}] window open. Log into the account/char for THIS window, "
              f"then use the panel (top-right).")
        try:
            control.run_panel(page, size["w"], size["h"])
        except KeyboardInterrupt:
            print(f"[{name}] stopped.")


if __name__ == "__main__":
    main()
