#!/usr/bin/env python3
"""Run a simulated game: player bots + parser writing game-state.json to site/."""
import sys
import os
import json
import socket
import threading
import time

sys.path.insert(0, os.path.dirname(__file__))
from monop_parser import MonopParser
from monop_players import PlayerBot

STATE_PATH = os.path.join(os.path.dirname(__file__), "site", "game-state.json")
HOST = "127.0.0.1"
PORT = 6667
CHANNEL = "#monop"
BOT_NICK = "monop"

class ParserClient:
    """IRC client that watches the game and writes game-state.json."""
    def __init__(self):
        self.parser = MonopParser()
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.buffer = ""
        self.running = True

    def connect(self):
        self.sock.connect((HOST, PORT))
        self.sock.sendall(b"NICK observer\r\nUSER observer 0 * :observer\r\n")
        time.sleep(1)
        self.sock.sendall(f"JOIN {CHANNEL}\r\n".encode())

    def run(self):
        self.connect()
        while self.running:
            try:
                data = self.sock.recv(4096)
                if not data:
                    break
                self.buffer += data.decode("utf-8", errors="replace")
                while "\r\n" in self.buffer:
                    line, self.buffer = self.buffer.split("\r\n", 1)
                    self._handle(line)
            except Exception as e:
                print(f"[parser] Error: {e}")
                break

    def _handle(self, line):
        if line.startswith("PING"):
            self.sock.sendall(f"PONG {line[5:]}\r\n".encode())
            return
        # Parse PRIVMSG from bot
        if "PRIVMSG" in line and CHANNEL in line:
            # :nick!user@host PRIVMSG #chan :message
            parts = line.split(f"PRIVMSG {CHANNEL} :", 1)
            if len(parts) == 2:
                prefix = parts[0].strip()
                sender = prefix.split("!")[0].lstrip(":")
                message = parts[1]
                ts = time.strftime("%Y-%m-%d %H:%M:%S")
                log_line = f"{ts}\t{sender}\t{message}"
                self.parser.parse_line(log_line)
                state = self.parser.get_state()
                if state:
                    from datetime import datetime, timezone
                    state["lastUpdated"] = datetime.now(timezone.utc).isoformat()
                    try:
                        with open(STATE_PATH, "w") as f:
                            json.dump(state, f, indent=2)
                    except Exception as e:
                        print(f"[parser] Write error: {e}")

    def stop(self):
        self.running = False
        try:
            self.sock.close()
        except:
            pass


def main():
    player_names = ["alice", "bob", "charlie"]

    # 1. Start parser/observer client FIRST so it sees setup messages
    pc = ParserClient()
    parser_thread = threading.Thread(target=pc.run, daemon=True)
    parser_thread.start()
    print(f"[game] Observer connected, writing to {STATE_PATH}")

    # 2. Wait for observer to be fully joined before bots trigger setup
    time.sleep(3)

    # 3. Start player bots (they'll trigger setup by sending player count)
    bots = []
    for i, name in enumerate(player_names):
        bot = PlayerBot(name, CHANNEL, HOST, PORT, player_names, i)
        t = threading.Thread(target=bot.run, daemon=True)
        t.start()
        bots.append(bot)
        time.sleep(3.0)  # stagger joins so setup is visible in the web UI

    print(f"[game] {len(bots)} player bots started")

    # Run until killed
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print("[game] Shutting down...")
        pc.stop()

if __name__ == "__main__":
    main()
