import asyncio
import uuid

from fastapi import FastAPI, WebSocket
from fastapi.logger import logger

from pymobiledevice3.services.web_protocol.cdp_target import CdpTarget
from pymobiledevice3.services.web_protocol.session_protocol import SessionProtocol
from pymobiledevice3.services.webinspector import WirTypes

app = FastAPI()


@app.on_event("startup")
async def startup_event():
    app.state.inspector.connect()


@app.get('/json')
async def available_targets():
    app.state.inspector.get_open_pages()
    targets = []
    for app_id in app.state.inspector.application_pages:
        for page_id, page in app.state.inspector.application_pages[app_id].items():
            if page.type_ not in (WirTypes.WEB, WirTypes.WEB_PAGE):
                continue
            targets.append({
                'description': '',
                'id': page_id,
                'title': page.web_title,
                'type': 'page',
                'url': page.web_url,
                'webSocketDebuggerUrl': f'ws://localhost:9222/devtools/page/{page_id}',
                'devtoolsFrontendUrl': f'/devtools/inspector.html?ws://localhost:9222/devtools/page/{page_id}',
            })
    return targets


@app.get('/json/version')
def version():
    return {
        'Browser': 'Safari',
        'Protocol-Version': '1.1',
        'User-Agent': 'pymobiledevice3',
        'V8-Version': '7.2.233',
        'WebKit-Version': '537.36 (@cfede9db1d154de0468cb0538479f34c0755a0f4)',
        'webSocketDebuggerUrl': f'ws://localhost:9222/devtools/browser/{app.state.inspector.connection_id}'
    }


async def from_cdp(target: CdpTarget, websocket):
    async for message in websocket.iter_json():
        logger.debug(f'CDP INPUT:  {message}')
        await target.send(message)


async def to_cdp(target: CdpTarget, websocket):
    while True:
        message = await target.receive()
        logger.debug(f'CDP OUTPUT:  {message}')
        await websocket.send_json(message)


@app.websocket('/devtools/page/{page_id}')
async def page_debugger(websocket: WebSocket, page_id: str):
    application, page = app.state.inspector.find_page_id(page_id)
    session_id = str(uuid.uuid4()).upper()
    protocol = SessionProtocol(app.state.inspector, session_id, application, page, method_prefix='')
    target = await CdpTarget.create(protocol)
    await websocket.accept()
    await asyncio.gather(
        from_cdp(target, websocket),
        to_cdp(target, websocket),
    )
