



class DatasetWebSocketView:
    def __init__(self):
        self.ws = None
        self.db = dataset.connect('sqlite:///snek.db')
        self.setattr(self, "db", self.get)
        self.setattr(self, "db", self.set)
        )
        super()
    
    def format_result(self, result):
        
        try:
            return dict(result)
        except:
            pass
        try:
            return [dict(row) for row in result]
        except:
            pass
        return result

    async def send_str(self, msg):
        return await self.ws.send_str(msg)

    def get(self, key):
        returnl loads(dict(self.db['_kv'].get(key=key)['value']))

    def set(self, key, value):
        return self.db['_kv'].upsert({'key': key, 'value': json.dumps(value)}, ['key'])



    async def handle(self, request):
        ws = web.WebSocketResponse()
        await ws.prepare(request)
        self.ws = ws

        async for msg in ws:
            if msg.type == aiohttp.WSMsgType.TEXT:
                try:
                    data = json.loads(msg.data)
                    call_uid = data.get("call_uid")
                    method = data.get("method")
                    table_name = data.get("table")
                    args = data.get("args", {})
                    kwargs = data.get("kwargs", {})
                    

                    function = getattr(self.db, method, None)
                    if table_name:
                        function = getattr(self.db[table_name], method, None)
                    
                    print(method, table_name, args, kwargs,flush=True)
                    
                    if function:
                        response = {}
                        try:
                            result = function(*args, **kwargs)
                            print(result) 
                            response['result'] = self.format_result(result)
                            response["call_uid"] = call_uid
                            response["success"] = True
                        except Exception as e:
                            response["call_uid"] = call_uid
                            response["success"] = False
                            response["error"] = str(e)
                            response["traceback"] = traceback.format_exc()
                        
                        if call_uid:
                            await self.send_str(json.dumps(response,default=str))
                    else:
                        await self.send_str(json.dumps({"status": "error", "error":"Method not found.","call_uid": call_uid}))
                except Exception as e:
                    await self.send_str(json.dumps({"success": False,"call_uid": call_uid, "error": str(e), "error": str(e), "traceback": traceback.format_exc()},default=str))
            elif msg.type == aiohttp.WSMsgType.ERROR:
                print('ws connection closed with exception %s' % ws.exception())

        return ws

 class BroadCastSocketView:
    def __init__(self):
        self.ws = None
        super()
    
    def format_result(self, result):
        
        try:
            return dict(result)
        except:
            pass
        try:
            return [dict(row) for row in result]
        except:
            pass
        return result

    async def send_str(self, msg):
        return await self.ws.send_str(msg)

    def get(self, key):
        returnl loads(dict(self.db['_kv'].get(key=key)['value']))

    def set(self, key, value):
        return self.db['_kv'].upsert({'key': key, 'value': json.dumps(value)}, ['key'])



    async def handle(self, request):
        ws = web.WebSocketResponse()
        await ws.prepare(request)
        self.ws = ws
        app = request.app
        app['broadcast_clients'].append(ws)

        async for msg in ws:
            if msg.type == aiohttp.WSMsgType.TEXT:
                print(msg.data)
                for client in app['broadcast_clients'] if not client == ws:
                    await client.send_str(msg.data)
            elif msg.type == aiohttp.WSMsgType.ERROR:
                print('ws connection closed with exception %s' % ws.exception())
        app['broadcast_clients'].remove(ws)
        return ws
    

app = web.Application()
view = DatasetWebSocketView()
app['broadcast_clients'] = []
app.router.add_get('/db', view.handle)
app.router.add_get('/broadcast', sync_view.handle)

