from fastapi import APIRouter
from typing import List
from enum import Enum
from pydantic import BaseModel

url = '/cameras'
swag_tags:List[str|Enum] = ["Cameras management"]
router = APIRouter(tags=swag_tags, prefix=url)

class CameraStatus(BaseModel):
    camera: str
    on_air: bool = False
    preview: bool = False
    
# Dictionnaire pour stocker le statut de chaque caméra par network puis par nom de caméra
camera_status: dict[str, dict[str, CameraStatus]] = {} 

class GetCameraStatusCmd(BaseModel):
    camera: str
    network: str

class CameraStatusResponse(BaseModel):
    camera: str
    network: str
    on_air: bool
    preview: bool
    other_cams : list[CameraStatus]|None = None

class SetCameraOnAiCmd(BaseModel):
    camera: str
    network: str
    on_air: bool

class SetCameraPreviewCmd(BaseModel):
    camera: str
    network: str
    preview: bool

@router.post('/status', response_model=CameraStatusResponse)
async def get_camera_status(cmd: GetCameraStatusCmd) -> CameraStatusResponse:
    """
    Get the status of a camera.

    - **camera**: The name of the camera to query.
    - **network**: the network the camera streams to.
    """
    cameras:dict[str, CameraStatus]|None = camera_status.get(cmd.network)
    if cameras is None:
        camera_status[cmd.network] = {}
        cameras = camera_status[cmd.network]
        cameras[cmd.camera] = CameraStatus(camera=cmd.camera)
        return CameraStatusResponse(camera=cmd.camera, network=cmd.network, on_air=False, preview=False)
    status:CameraStatus|None = cameras.get(cmd.camera)
    if status is None:
        cameras[cmd.camera] = CameraStatus(camera=cmd.camera)
        return CameraStatusResponse(camera=cmd.camera, network=cmd.network, on_air=False, preview=False)
    return CameraStatusResponse(camera=cmd.camera, network=cmd.network, on_air=status.on_air, preview=status.preview)

@router.post('/setonair', response_model=CameraStatusResponse)
async def set_on_air(cmd: SetCameraOnAiCmd) -> CameraStatusResponse:
    """
    Set the on-air status of a camera.

    - **camera**: The name of the camera to update.
    - **on_air**: The new on-air status (true or false).
    - **network**: the network the camera streams to.
    """
    # Mettre à jour le statut de la caméra dans le dictionnaire
    preview = False
    cameras:dict[str, CameraStatus]|None = camera_status.get(cmd.network)
    if cameras is None:
        cameras = {}
        cameras[cmd.camera] = CameraStatus(camera=cmd.camera, on_air = cmd.on_air)
        camera_status[cmd.network] = cameras
    else:
        status = cameras.get(cmd.camera)
        if status:
            status.on_air = cmd.on_air
            preview = status.preview
        else:
            cameras[cmd.camera] = CameraStatus(camera=cmd.camera, on_air = cmd.on_air)

    for name, c in cameras.items():
        if name != cmd.camera and c.on_air:
            c.on_air = False
    
    # itérer sur les autres caméras du même network pour les ajouter à la réponse
    other_cams = [CameraStatus(camera=c.camera, on_air=c.on_air, preview=c.preview) for name, c in cameras.items() if name != cmd.camera]
    return CameraStatusResponse(camera=cmd.camera, on_air=cmd.on_air, preview=preview, network=cmd.network, other_cams=other_cams)

@router.post('/setpreview', response_model=CameraStatusResponse)
async def set_preview(cmd: SetCameraPreviewCmd) -> CameraStatusResponse:
    """
    Set the preview status of a camera.

    - **camera**: The name of the camera to update.
    - **preview**: The new preview status (true or false).
    - **network**: the network the camera streams to.
    """
    # Mettre à jour le statut de la caméra dans le dictionnaire
    on_air = False
    cameras:dict[str, CameraStatus]|None = camera_status.get(cmd.network)
    if cameras is None:
        cameras = {}
        cameras[cmd.camera] = CameraStatus(camera=cmd.camera, preview=cmd.preview)
        camera_status[cmd.network] = cameras
    else:
        status = cameras.get(cmd.camera)
        if status:
            status.preview = cmd.preview
            on_air = status.on_air
        else:
            cameras[cmd.camera] = CameraStatus(camera=cmd.camera, preview=cmd.preview)

    for name, c in cameras.items():
        if name != cmd.camera and c.preview:
            c.preview = False
            
    # itérer sur les autres caméras du même network pour les ajouter à la réponse
    other_cams = [CameraStatus(camera=c.camera, on_air=c.on_air, preview=c.preview) for name, c in cameras.items() if name != cmd.camera]
    return CameraStatusResponse(camera=cmd.camera, on_air=on_air, preview=cmd.preview, network=cmd.network, other_cams=other_cams)
