# -*- coding: utf-8 -*-
import datetime
import logging
from types import MethodType

from aiohttp import WSMsgType, web

LOGGER = logging.getLogger('homehub.lib.websocket')


async def get_websocket(request):
    response = web.WebSocketResponse()
    await response.prepare(request)

    response['SUBSCRIBER_ID'] = datetime.datetime.now().isoformat()
    request.config_dict['SUBSCRIBERS'].append(response)

    async for msg in response:
        if msg.type == WSMsgType.TEXT:
            LOGGER.debug('Received message: {data}'.format(data=msg.data))
        elif msg.type == WSMsgType.ERROR:
            LOGGER.error('WebSocket exception', exc_info=response.exception())

    LOGGER.debug('WebSocket connection closed.')
    request.config_dict['SUBSCRIBERS'].remove(response)

    return response


async def notify_subscribers(app, payload):
    for subscriber in app['SUBSCRIBERS']:
        LOGGER.debug('Notifying subscriber: {subscriber_id}, closed={closed}'.format(
            subscriber_id=subscriber['SUBSCRIBER_ID'],
            closed=subscriber.closed,
        ))

        try:
            if not subscriber.closed:
                await subscriber.send_json(payload)
        except Exception as exc:
            LOGGER.error(
                'Error notifying subscriber: {subscriber_id}, closed={closed}'.format(
                    subscriber_id=subscriber['SUBSCRIBER_ID'],
                    closed=subscriber.closed,
                ),
                exc_info=exc,
            )


def setup(app):
    app['SUBSCRIBERS'] = []
    app.notify_subscribers = MethodType(notify_subscribers, app)

    app.add_routes([
        web.get('/backend/websocket', get_websocket),
    ])

    async def on_shutdown(app):
        for subscriber in app['SUBSCRIBERS']:
            if not subscriber.closed:
                await subscriber.close()

    app.on_shutdown.append(on_shutdown)
