# Copyright (c) Huawei Technologies Co., Ltd. 2026-2026. All rights reserved.
# OpenOLC 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 typing import List

from olc.bean.tag_group import TagGroup
from olc.control.context.context import OlcContext
from olc.control.handler.admission_handler import AdmissionHandler
from olc.control.handler.flow_handler import FlowHandler
from olc.control.handler.group_matcher_handler import GroupMatcherHandler
from olc.control.handler.statistic_handler import StatisticHandler
from olc.control.handler_chain.box_handler import AbsBoxHandler


class FirstBoxHandler(AbsBoxHandler):
    """链表头哨兵 —— 自身无业务,仅作为链路起点。"""

    def do_in_coming(self, context: OlcContext, groups: List[TagGroup]):
        return None  # 不改写 groups,直接透传

    def do_out_coming(self, context: OlcContext):
        return None


class DefaultBoxHandlerChain:
    def __init__(self):
        self.first_box: AbsBoxHandler = FirstBoxHandler()
        self.end_box: AbsBoxHandler = self.first_box

    def add_last_box(self, handler: AbsBoxHandler):
        """
            将handler添加到调用链后面
        :param handler:
        :return:
        """
        handler.set_private(self.end_box)
        self.end_box.set_next(handler)
        self.end_box = handler
        return self

    # ==== 同步接口 ====
    def in_coming(self, context: OlcContext, groups: List[TagGroup]):
        self.first_box.in_coming(context, groups)

    def out_coming(self, context: OlcContext):
        self.end_box.out_coming(context)

    # ==== 异步接口 ====
    async def async_in_coming(self, context: OlcContext, groups: List[TagGroup]):
        await self.first_box.async_in_coming(context, groups)

    async def async_out_coming(self, context: OlcContext):
        await self.end_box.async_out_coming(context)


class OlcHandlerChain:
    chain = DefaultBoxHandlerChain()
    chain.add_last_box(GroupMatcherHandler())
    chain.add_last_box(AdmissionHandler())
    chain.add_last_box(FlowHandler())
    chain.add_last_box(StatisticHandler())

    @classmethod
    def add_last(cls, handler: AbsBoxHandler):
        cls.chain.add_last_box(handler)

    @classmethod
    def get_chain(cls) -> DefaultBoxHandlerChain:
        return cls.chain