from snek.system.view import BaseView 
import functools 
from aiohttp import web 

class ContainerView(BaseView):


    async def stdout_event_handler(self, ws, data):
        try:
            await ws.send_bytes(data)
        except Exception as ex:
            print(ex)
            await ws.close()
            return False 
        return True 

    async def create_stdout_event_handler(self, ws):
        return functools.partial(self.stdout_event_handler, ws)

    async def get(self):

        ws = web.WebSocketResponse()
        await ws.prepare(self.request)
        if not self.request.session.get("logged_in"):
            return self.HTTPUnauthorized()

        channel_uid = self.request.match_info.get("channel_uid")
        channel_member = await self.services.channel_member.get(channel_uid=channel_uid, user_uid=self.request.session.get("uid"))
        if not channel_member:
            return web.HTTPUnauthorized()
        
        container = await self.services.container.get(channel_uid)
        if not container:
            return web.HTTPNotFound()

        if not container['status'] == 'running':
            resp = await self.services.container.start(channel_uid)
            await ws.send_str(str(resp))

        container_name = await self.services.container.get_container_name(channel_uid)
        
        event_handler = await self.create_stdout_event_handler(ws)

        await self.services.container.add_event_listener(container_name, "stdout", event_handler)

        while True:
            data = await ws.receive()
            if data.type == web.WSMsgType.TEXT:

                await self.services.container.write_stdin(container_name, data.data)
            elif data.type == web.WSMsgType.CLOSE:
                break
            elif data.type == web.WSMsgType.ERROR:
                break

        await self.services.container.remove_event_listener(container_name, channel_uid, "stdout")

        return ws 


