import asyncio
import queue

from ldnode import logger
from ldnode.runner.schemas import BaseWorkerState, Service
from ldnode.runner.config import Settings
from ldnode.runner.schemas import BaseContext
from ldnode.runner.events import Events
from .schemas.enumerations import SyncStatus
from .schemas.models import SyncResult
from .worker import LoaderWorker


class LoaderService(Service):
    """ 加载服务 """
    def __init__(self, settings: Settings, context: BaseContext):
        super().__init__(settings, context)
        self.worker: BaseWorkerState | None = None
        self.end_flag = asyncio.Event()
        self.listen_task: asyncio.Task | None = None
        self.running = False
        
    async def listen_worker_output(self, state: BaseWorkerState) -> None:
        """ 监听工作进程输出 """
        while self.running:
            try:
                result: SyncResult= await state.recv()
                if result is not None:
                    is_ok = result.status == SyncStatus.SUCCESS or result.status == SyncStatus.NO_CHANGE
                    await self.context.submit_event(state.get_worker_id(), Events.DATA_SYNC, {
                        "filename": result.filename,
                        "is_ok": is_ok,
                        "latest_tag": result.latest_tag_or_error if is_ok else "",
                        "error_message": result.latest_tag_or_error if not is_ok else "",
                    })
            except queue.Empty:
                continue
            except Exception as e:
                logger.loader.warning(f"{state.get_worker_id()} 监听工作进程输出失败: {e}")
        
    async def start(self) -> None:
        """ 启动服务 """
        self.running = True
        self.worker = await self.context.register_worker(
            worker_name="loader",
            worker_id=0,
            worker_cls=LoaderWorker,
        )
        self.listen_task = asyncio.create_task(self.listen_worker_output(self.worker))
        await self.end_flag.wait()
        
    async def shutdown(self) -> None:
        """ 关闭服务 """
        self.running = False
        if self.listen_task:
            await self.listen_task
        self.end_flag.set()
