import zfit
from zfit import Parameter

from ..settings import run as run, ztypes as ztypes
from ..util import ztyping as ztyping
from ..util.cache import invalidate_graph as invalidate_graph
from ..util.deprecation import deprecated as deprecated, deprecated_norm_range as deprecated_norm_range
from ..util.exception import AlreadyExtendedPDFError as AlreadyExtendedPDFError, BreakingAPIChangeError as BreakingAPIChangeError, FunctionNotImplemented as FunctionNotImplemented, NormNotImplemented as NormNotImplemented, NotExtendedPDFError as NotExtendedPDFError, SpecificFunctionNotImplemented as SpecificFunctionNotImplemented
from ..util.plotter import PDFPlotter as PDFPlotter
from ..util.ztyping import ExtendedInputType as ExtendedInputType, NormInputType as NormInputType
from .basemodel import BaseModel as BaseModel
from .baseobject import extract_filter_params as extract_filter_params
from .parameter import Parameter as Parameter, convert_to_parameter as convert_to_parameter
from .sample import extended_sampling as extended_sampling
from .space import Space as Space, convert_to_space as convert_to_space
from collections.abc import Iterable
from zfit import z as z
from zfit._interfaces import ZfitPDF as ZfitPDF, ZfitParameter as ZfitParameter, ZfitSpace as ZfitSpace

class PDFMeta(type):
    def __call__(cls, *args, obs=None, **kwargs): ...

class BasePDF(ZfitPDF, BaseModel, metaclass=PDFMeta):
    def __init__(self, obs: ztyping.ObsTypeInput, params: dict[str, ZfitParameter] | None = None, *, dtype=..., label=None, extended: ExtendedInputType = None, norm: NormInputType = None, name: str = 'BasePDF', **kwargs) -> None: ...
    def __init_subclass__(cls, **kwargs) -> None: ...
    @property
    def label(self) -> str: ...
    @property
    def norm_range(self) -> Space | None | bool: ...
    @property
    def norm(self) -> Space | None | bool: ...
    @invalidate_graph
    def set_norm_range(self, _: ztyping.LimitsTypeInput): ...
    def normalization(self, norm: ztyping.LimitsType = None, *, options=None, limits: ztyping.LimitsType = None, params: ztyping.ParamsTypeOpt = None) -> ztyping.XType: ...
    def unnormalized_pdf(self, x: ztyping.XType) -> ztyping.XType: ...
    @deprecated_norm_range
    def ext_pdf(self, x: ztyping.XTypeInput, norm: ztyping.LimitsTypeInput = None, *, params: ztyping.ParamsTypeOpt = None) -> ztyping.XType: ...
    @deprecated_norm_range
    def ext_log_pdf(self, x: ztyping.XTypeInput, norm: ztyping.LimitsTypeInput = None, *, params: ztyping.ParamsTypeOpt = None) -> ztyping.XType: ...
    @deprecated_norm_range
    def pdf(self, x: ztyping.XTypeInput, norm: ztyping.LimitsTypeInput = None, *, params: ztyping.ParamsTypeOpt = None) -> ztyping.XType: ...
    @deprecated_norm_range
    def log_pdf(self, x: ztyping.XType, norm: ztyping.LimitsType = None, *, params: ztyping.ParamsTypeOpt = None) -> ztyping.XType: ...
    def log_normalization(self, norm: ztyping.LimitsType, *, options=None, params: ztyping.ParamsTypeOpt = None) -> ztyping.XType: ...
    @deprecated_norm_range
    def ext_integrate(self, limits: ztyping.LimitsType, norm: ztyping.LimitsType = None, *, options=None, params: ztyping.ParamsTypeOpt = None) -> ztyping.XType: ...
    def create_extended(self, yield_: ztyping.ParamTypeInput, name: str | None = None, *, name_addition: str | None = None) -> 'BasePDF': ...
    def to_positive(self, epsilon: float = 1e-100, name: str | None = None) -> zfit.pdf.PositivePDF: ...
    def to_cached(self, epsilon: float | None = None, name: str | None = None) -> zfit.pdf.CachedPDF: ...
    def set_yield(self, value) -> None: ...
    @property
    def is_extended(self) -> bool: ...
    def get_yield(self) -> Parameter | None: ...
    @property
    def extended(self) -> Parameter | None: ...
    def create_projection_pdf(self, *, limits: ztyping.LimitsTypeInput = None, obs: ztyping.LimitsTypeInput = None, options=None, name: str | None = None, label: str | None = None, extended: ExtendedInputType = None, norm: NormInputType = None) -> ZfitPDF: ...
    def copy(self, **override_parameters) -> BasePDF: ...
    @deprecated_norm_range
    def as_func(self, norm: ztyping.LimitsType = False): ...
    def to_unbinned(self) -> ZfitPDF: ...
    def to_binned(self, space: ztyping.SpaceType, extended: ExtendedInputType = None, norm: NormInputType = None, name: str | None = None, label: str | None = None): ...
    def to_truncated(self, limits: ZfitSpace | Iterable[ZfitSpace] | None = None, *, obs=None, extended=None, norm=None, name: str | None = None, label: str | None = None): ...

    def get_params(
        self,
        floating: bool | None = True,
        is_yield: bool | None = None,
        extract_independent: bool | None = True,
        *,
        autograd: bool | None = None,
    ) -> set[Parameter]:...
