from __future__ import annotations

from typing import Any, Tuple, TypeVar, overload

from numpy.typing import ArrayLike

T = TypeVar("T", bound="_BaseAccumulator")

class _BaseAccumulator:
    def __eq__(self, other: Any) -> bool: ...
    def __ne__(self, other: Any) -> bool: ...
    def __imul__(self: T, other: float) -> T: ...
    def __repr__(self) -> str: ...
    def __copy__(self: T) -> T: ...
    def __deepcopy__(self: T, memo: Any) -> T: ...
    def _ipython_key_completions_(self) -> tuple[str, ...]: ...

class WeightedSum(_BaseAccumulator):
    @overload
    def __init__(self) -> None: ...
    @overload
    def __init__(self, value: float) -> None: ...
    @overload
    def __init__(self, value: float, variance: float) -> None: ...
    @property
    def value(self) -> float: ...
    @property
    def variance(self) -> float: ...
    def __iadd__(self: T, arg0: float) -> T: ...
    def fill(self: T, value: ArrayLike, variance: ArrayLike | None = None) -> T: ...
    @staticmethod
    def _make(a: ArrayLike, b: ArrayLike) -> WeightedSum: ...
    @staticmethod
    def _array(a: ArrayLike, b: ArrayLike) -> WeightedSum: ...
    def __getitem__(self, key: str) -> float: ...
    def __setitem__(self, key: str, value: float) -> None: ...

class Sum(_BaseAccumulator):
    @overload
    def __init__(self) -> None: ...
    @overload
    def __init__(self, value: float) -> None: ...
    @property
    def value(self) -> float: ...
    def __iadd__(self: T, arg0: float) -> T: ...
    def fill(self: T, value: ArrayLike) -> T: ...
    @property
    def _small(self) -> float: ...
    @property
    def _large(self) -> float: ...

class WeightedMean(_BaseAccumulator):
    @overload
    def __init__(self) -> None: ...
    @overload
    def __init__(
        self,
        sum_of_weights: float,
        sum_of_weights_squared: float,
        value: float,
        variance: float,
    ) -> None: ...
    @property
    def sum_of_weights(self) -> float: ...
    @property
    def sum_of_weights_squared(self) -> float: ...
    @property
    def value(self) -> float: ...
    @property
    def _sum_of_weighted_deltas_squared(self) -> float: ...
    @property
    def variance(self) -> float: ...
    def __call__(
        self: T, value: ArrayLike, *, weight: ArrayLike | None = None
    ) -> T: ...
    def fill(self: T, value: ArrayLike, *, weight: ArrayLike | None = None) -> T: ...
    @staticmethod
    def _make(
        arg0: ArrayLike, arg1: ArrayLike, arg2: ArrayLike, arg3: ArrayLike
    ) -> WeightedMean: ...
    @staticmethod
    def _array(
        arg0: ArrayLike, arg1: ArrayLike, arg2: ArrayLike, arg3: ArrayLike
    ) -> WeightedMean: ...
    def __getitem__(self, key: str) -> float: ...
    def __setitem__(self, key: str, value: float) -> None: ...

class Mean(_BaseAccumulator):
    @overload
    def __init__(self) -> None: ...
    @overload
    def __init__(self, count: float, value: float, variance: float) -> None: ...
    @property
    def count(self) -> float: ...
    @property
    def value(self) -> float: ...
    @property
    def _sum_of_deltas_squared(self) -> float: ...
    @property
    def variance(self) -> float: ...
    def __call__(
        self: T, value: ArrayLike, *, weight: ArrayLike | None = None
    ) -> T: ...
    def fill(self: T, value: ArrayLike, *, weight: ArrayLike | None = None) -> T: ...
    @staticmethod
    def _make(arg0: ArrayLike, arg1: ArrayLike, arg2: ArrayLike) -> Mean: ...
    @staticmethod
    def _array(arg0: ArrayLike, arg1: ArrayLike, arg2: ArrayLike) -> Mean: ...
    def __getitem__(self, key: str) -> float: ...
    def __setitem__(self, key: str, value: float) -> None: ...
