#!/usr/bin/env python
import asyncio
import logging
logger = logging.getLogger("chatkit:" + __name__)


class WSClientManager:
    def __init__(self):
        self._clients = []

    def all(self):
        return self._clients

    def add(self, client):
        logging.info("+ WSClient {}".format(client))
        self._clients.append(client)

    def remove(self, client):
        logging.info("- WSClient {}".format(client))
        self._clients.remove(client)


class WSClient:
    objects = WSClientManager()

    def __init__(self, server, ws, user=None, token=None):
        self.server = server
        self._ws = ws
        self.user = user
        self.token = token
        WSClient.objects.add(self)

    @asyncio.coroutine
    def disconnect(self, message):
        self.server.disconnect(self, message)

    @asyncio.coroutine
    def send(self, data):
        if self._ws.state != "OPEN":
            logging.info("WS state not OPEN, disconnecting" +
                         str(self.user))
            self.disconnect("WS state not OPEN.")
            return

        logging.info("> {} {}".format(self.user, data))
        yield from self._ws.send(data)

    @asyncio.coroutine
    def send_one(self, to_client, data):
        if to_client._ws.state != "OPEN":
            to_client.disconnect("WS state not OPEN.")

        yield from to_client._ws.send(data)
        logging.info("> {} {}".format(to_client.user, data))

    @asyncio.coroutine
    def send_all(self, from_client, data):
        for c in WSClient.clients:
            yield from self.send_one(c, data)

    @asyncio.coroutine
    def send_others(self, from_client, data):
        for c in WSClient.clients:
            if c != from_client:
                yield from self.send_one(c, data)

    @asyncio.coroutine
    def get_others(self, client):
        for c in WSClient.clients:
            resp = "join {}".format(c.user.username)
            yield from self.send_one(self, resp)
