from micropie import App
from collections import deque
import json
import asyncio


class ChatApp(App):
    def __init__(self):
        super().__init__()
        self.messages = deque(maxlen=100)
        self.clients = set()

    async def index(self):
        # Inline HTML for demo purposes
        html = """
        <!doctype html>
        <title>Micropie Chat SSE</title>
        <h1>Micropie Chat SSE Demo</h1>
        <form id="chat-form">
          Name: <input id="username" value="Anonymous" size="10">
          <input id="message" autocomplete="off" size="40">
          <button>Send</button>
        </form>
        <pre id="log"></pre>
        <script>
        const log = document.getElementById('log');
        const usernameInput = document.getElementById('username');
        const messageInput = document.getElementById('message');
        const form = document.getElementById('chat-form');

        const evtSource = new EventSource('/events');
        evtSource.onmessage = function(event) {
          const data = JSON.parse(event.data);
          log.textContent += data.username + ": " + data.message + "\\n";
        };

        form.onsubmit = async function(e) {
          e.preventDefault();
          await fetch('/send', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({
              username: usernameInput.value,
              message: messageInput.value,
            })
          });
          messageInput.value = "";
        };
        </script>
        """
        return 200, html, [("Content-Type", "text/html")]

    async def send(self):
        data = self.request.get_json
        username = data.get("username", "Anonymous")
        message = data.get("message", "")
        if message.strip():
            msg = {"username": username, "message": message}
            self.messages.append(msg)
            # Broadcast to all connected clients
            for client in self.clients.copy():
                try:
                    await client.put(json.dumps(msg))
                except Exception:
                    self.clients.discard(client)
        return 200, {"status": "success"}

    async def events(self):
        async def stream():
            queue = asyncio.Queue()
            self.clients.add(queue)
            try:
                for msg in self.messages:
                    yield f"data: {json.dumps(msg)}\n\n"
                while True:
                    try:
                        msg = await queue.get()
                        if msg is None:
                            break
                        yield f"data: {msg}\n\n"
                    except asyncio.CancelledError:
                        break
            finally:
                self.clients.discard(queue)

        return (
            200,
            stream(),
            [
                ("Content-Type", "text/event-stream"),
                ("Cache-Control", "no-cache"),
                ("Connection", "keep-alive"),
            ],
        )


app = ChatApp()
