from __future__ import annotations
import weakref
from abc import ABC
from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from typing import Any, Callable
__all__ = ["Stat"]
[docs]class Stat(ABC):
    """
    A container for an Entities Stat and related functionality.
    `base_value` is used as the reference for modifiers.
    `value` is the result after modifiers are applied.
    `override` forces a specific value to be used, ignoring modifiers.
    """
[docs]    def __init__(self, base_value):
        self._base_value = base_value
        # weakkey dict will drop modifiers if they have been deleted
        self._modifiers = weakref.WeakKeyDictionary()
        self._override_value = None 
[docs]    def reset(self):
        """
        Remove any modifiers and override.
        """
        self._override_value = None
        self._modifiers.clear() 
    @property
    def value(self):
        if self._override_value is not None:
            return self._override_value
        acc = 0
        for key, func in self._modifiers.items():
            acc += func(self._base_value)
        return self._base_value + acc
    @property
    def base_value(self):
        return self._base_value
    @base_value.setter
    def base_value(self, value):
        """
        Set the base or original value for the Stat.
        """
        self._base_value = value
[docs]    def override(self, value):
        """
        Force the value and ignore modifiers
        """
        self._override_value = value 
[docs]    def apply_modifier(self, func: Callable, key: Any):
        """
        Add a modifier
        When value is calculated, ``func`` will be called with the base value
        Args:
            func: Any callable function
            key: Unique identifier for adding and removing
        """
        self._modifiers[key] = func 
[docs]    def remove_modifier(self, key: Any):
        """
        Remove a modifier
        Args:
            key: Unique identifier for adding and removing
        """
        del self._modifiers[key] 
[docs]    def has_modifier(self, key: Any):
        """
        Check if modifier is applied
        Args:
            key: Unique identifier for adding and removing
        """
        return key in self._modifiers