from fastapi import APIRouter, HTTPException, status, WebSocket, Request
from sse_starlette.sse import EventSourceResponse
import base64
import docker
import aiodocker
from asyncio import sleep

router = APIRouter()
client = docker.from_env()
docker = aiodocker.Docker()

@router.post("/server/{server}/start")
async def start(server):
    try:
        container = await getContainer(server) 
        await container.start()
    except:
        raise HTTPException(status_code=500)
    return server

@router.post("/server/{server}/stop")
async def stop(server):
    try:
        container = await getContainer(server) 
        await container.stop()
    except:
        raise HTTPException(status_code=500)
    return server

@router.post("/server/{server}/command/{command}",
    description="Take server and base64 encoded command")
async def commnd(server, command):
    try:
        container = client.containers.get(server)
        print(command)
        cmd = base64.urlsafe_b64decode(command).decode('utf_8')
        print(cmd)        
        container.exec_run(cmd="/usr/local/bin/cmd " + str(cmd))
        s= 200
        running="Success"
    except:
        raise HTTPException(status_code=500)
    
    return f"{server} {base64.urlsafe_b64decode(command).decode('utf_8')}"


@router.get("/server/{server}/logs")
async def logs(server: str, request: Request, follow: bool = True, tail: int = 1000):
    container = await getContainer(server)
    #event_generator = logGenerator(request, server)
    if follow:
        return EventSourceResponse(logStream(container, tail))
    else:
        return await container.log(stdout=True, follow=False, tail=tail)

async def logStream(container, tail):
    async for line in container.log(stdout=True, follow=True, tail=tail):
        yield line
        yield '\n'

@router.get("/server/{server}/stats")
async def stats(server: str, request: Request, stream: bool = True, delay: int = 2):
    container = await getContainer(server)
    if stream:
        return EventSourceResponse(statStream(request, container, delay))   
    return await container.stats(stream=False)

async def statStream(request, container, delay):
    while True:
        yield await container.stats(stream=False)
        _delay = delay - 1 if delay else 0
        print(_delay)
        await sleep(_delay)

async def getContainer(server):
    return await docker.containers.get(server)