# Copyright (c) Huawei Technologies Co., Ltd. 2026-2026. All rights reserved.
# MindIE is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#         `http://license.coscl.org.cn/MulanPSL2`
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.

from abc import ABC, abstractmethod
from typing import List, Optional

from olc.bean.tag_group import TagGroup
from olc.control.context.context import OlcContext


class BoxHandler(ABC):
    """
        如果子类不涉及 I/O 等阻塞操作,只需要实现 do_*, 涉及阻塞操作需要做同步异步镜像实现

        链路推进由 AbsBoxHandler 统一接管。
    """

    # ========= 同步实现 ===========
    @abstractmethod
    def do_in_coming(
            self, context: OlcContext, groups: List[TagGroup]
    ) -> Optional[List[TagGroup]]:
        """业务前置处理。

        :return: None 沿用入参 groups;非 None 替换传给下游(GroupMatcherHandler 使用)
        """

    @abstractmethod
    def do_out_coming(self, context: OlcContext) -> None:
        """业务后置处理。"""

    # ===== 异步实现 ========
    async def async_do_in_coming(
            self, context: OlcContext, groups: List[TagGroup]
    ) -> Optional[List[TagGroup]]:
        """ 默认由调用同步实现, 如有阻塞操作需要重写 """
        return self.do_in_coming(context, groups)

    async def async_do_out_coming(self, context: OlcContext) -> None:
        """ 默认由调用同步实现, 如有阻塞操作需要重写 """
        self.do_out_coming(context)


class AbsBoxHandler(BoxHandler, ABC):
    """链路推进基类 —— 统一接管 in_coming/out_coming,子类实现 do_*。
    """

    # 子类可覆盖:若为 False,则即便 context.stop=True 也仍执行 do_in_coming操作
    stop_aware: bool = True

    def __init__(
            self,
            next_handler: "AbsBoxHandler" = None,
            private_handler: "AbsBoxHandler" = None,
    ):
        self.next_handler = next_handler
        self.private_handler = private_handler

    # ---- 同步路径 ----

    def in_coming(self, context: OlcContext, groups: List[TagGroup]) -> None:
        next_groups = groups
        if not (self.stop_aware and context.stop):
            ret = self.do_in_coming(context, groups)
            if ret is not None:
                next_groups = ret
        self._next_in_coming(context, next_groups)

    def out_coming(self, context: OlcContext) -> None:
        self.do_out_coming(context)
        self._next_out_coming(context)

    # ---- 异步路径 ----

    async def async_in_coming(
            self, context: OlcContext, groups: List[TagGroup]
    ) -> None:
        next_groups = groups
        if not (self.stop_aware and context.stop):
            ret = await self.async_do_in_coming(context, groups)
            if ret is not None:
                next_groups = ret
        await self._async_next_in_coming(context, next_groups)

    async def async_out_coming(self, context: OlcContext) -> None:
        await self.async_do_out_coming(context)
        await self._async_next_out_coming(context)

    # ---- 内部链路辅助 ----

    def _next_in_coming(self, context: OlcContext, groups: List[TagGroup]):
        if self.next_handler is not None:
            self.next_handler.in_coming(context, groups)

    def _next_out_coming(self, context: OlcContext):
        if self.private_handler is not None:
            self.private_handler.out_coming(context)

    async def _async_next_in_coming(self, context: OlcContext, groups: List[TagGroup]):
        if self.next_handler is not None:
            await self.next_handler.async_in_coming(context, groups)

    async def _async_next_out_coming(self, context: OlcContext):
        if self.private_handler is not None:
            await self.private_handler.async_out_coming(context)

    # ---- 链路构造(DefaultBoxHandlerChain 用)----

    def get_private(self) -> "AbsBoxHandler":
        return self.private_handler

    def get_next(self) -> "AbsBoxHandler":
        return self.next_handler

    def set_private(self, private_handler: "AbsBoxHandler"):
        self.private_handler = private_handler

    def set_next(self, next_handler: "AbsBoxHandler"):
        self.next_handler = next_handler