import os
from numbers import Real

from behaviors.behavior import Behavior
from behaviors.custom.keyframe.keyframe import KeyframeSkill


class Kick(Behavior):
    SHORT_MAX_DISTANCE: float = 1.8
    MID_MAX_DISTANCE: float = 4.5
    TEN_METER_MIN_DISTANCE: float = 8.0
    DEFAULT_DISTANCE: float = 3.0

    def __init__(self, agent):
        super().__init__(agent)

        base_dir = os.path.dirname(__file__)
        self.short_kick = KeyframeSkill(
            agent=agent,
            file=os.path.join(base_dir, "kick_short.yaml"),
        )
        self.mid_kick = KeyframeSkill(
            agent=agent,
            file=os.path.join(base_dir, "kick_mid.yaml"),
        )
        self.long_kick = KeyframeSkill(
            agent=agent,
            file=os.path.join(base_dir, "kick_long.yaml"),
        )
        self.ten_meter_kick = KeyframeSkill(
            agent=agent,
            file=os.path.join(base_dir, "kick_10m.yaml"),
        )

        self.current_kick: KeyframeSkill | None = None
        self.should_reset_kick: bool = True
        self.should_execute_neutral: bool = True

    def execute(self, reset: bool, *args, **kwargs) -> bool:
        if reset:
            kick_distance = self._extract_kick_distance(*args, **kwargs)
            self.current_kick = self._choose_kick_from_distance(kick_distance)
            self.should_reset_kick = True
            self.should_execute_neutral = True

        if self.current_kick is None:
            self.current_kick = self.mid_kick

        if self.should_execute_neutral:
            neutral_finished = self.agent.skills_manager.execute(
                "Neutral",
            )
            self.should_reset_kick = False
            if not neutral_finished:
                return False
            self.should_execute_neutral = False
            self.should_reset_kick = True

        has_finished = self.current_kick.execute(reset=self.should_reset_kick)
        self.should_reset_kick = False
        return has_finished

    def _extract_kick_distance(self, *args, **kwargs) -> float:
        distance_candidates = (
            kwargs.get("distance"),
            kwargs.get("kick_distance"),
            kwargs.get("target_distance"),
            kwargs.get("ball_to_target_distance"),
            args[0] if args else None,
        )

        for candidate in distance_candidates:
            if isinstance(candidate, Real):
                return float(max(0.0, candidate))

        return self.DEFAULT_DISTANCE

    def _choose_kick_from_distance(self, distance: float) -> KeyframeSkill:
        if distance <= self.SHORT_MAX_DISTANCE:
            return self.short_kick

        if distance <= self.MID_MAX_DISTANCE:
            return self.mid_kick

        if distance >= self.TEN_METER_MIN_DISTANCE:
            return self.ten_meter_kick

        return self.long_kick

    def is_ready(self, *args) -> bool:
        return True
