from time import sleep
from typing import Optional

import socketio

from server.game.lobby import LobbyManager, Metadata
from server.model.hand import Hand
from server.model.players import Player, Announce

sio = socketio.AsyncServer(
    async_mode='asgi',
    logger=True,
    cors_allowed_origins="*"  # FIXME: CSRF Vulnerability
)
lobby = LobbyManager(sio)


class ClientPlayer(Player):
    def __init__(self, lobby: LobbyManager):
        super().__init__()
        self.lobby = lobby
        self.ready = False

    async def announce(self, current_bet: Optional[Hand]) -> Announce:
        metadata: Metadata = self.lobby.metadata[self.name]
        print(f"Asking Client {self.name} for announce...")

        while not metadata.last_announce and metadata.fresh_announce:
            print("While, send_waiting_for")
            await lobby.send_waiting_for(self)
            print(f"Still waiting for {self.name}'s announce...")
            sleep(5)

        print(f"Client announced: {metadata.last_announce.bet}!")
        got_announce = metadata.last_announce
        metadata.fresh_announce = False
        return got_announce


@sio.event
async def connect(sid, environ):
    print("[WS] Connect ", sid, environ)
    player = ClientPlayer(lobby)
    await lobby.new_player(player, sid)


@sio.event
async def message(sid, data):
    print("[WS] Message ", data)
    await lobby.handle_message(sid, data)


@sio.on("pingServer")
async def ping_server(sid, data):
    print("[WS] Ping received:", data)
    await sio.emit('messageChannel', '{"extras":{"message":"PONG"}}', room=sid)


@sio.event
async def disconnect(sid):
    print('[WS] Disconnect ', sid)
    await lobby.player_left(sid)
