import numpy as np
from numpy.typing import NDArray

# RSCM uses 64bit floats throughout
Arr = NDArray[np.float64]
F = np.float64 | float

class StateValue:
    """Represents a value that can be scalar or spatially-resolved.

    In the Rust core, this is an enum with three variants:
      - Scalar(float): A single global value
      - FourBox(FourBoxSlice): Four-box regional values
      - Hemispheric(HemisphericSlice): Hemispheric values
    """

    @staticmethod
    def scalar(value: float) -> StateValue:
        """Create a scalar StateValue."""
        ...
    @staticmethod
    def four_box(slice: FourBoxSlice) -> StateValue:
        """Create a FourBox StateValue from a FourBoxSlice."""
        ...
    @staticmethod
    def hemispheric(slice: HemisphericSlice) -> StateValue:
        """Create a Hemispheric StateValue from a HemisphericSlice."""
        ...
    def is_scalar(self) -> bool:
        """Check if this is a scalar value."""
        ...
    def is_four_box(self) -> bool:
        """Check if this is a FourBox grid value."""
        ...
    def is_hemispheric(self) -> bool:
        """Check if this is a Hemispheric grid value."""
        ...
    def as_scalar(self) -> float | None:
        """Get the scalar value if this is a Scalar variant, otherwise None."""
        ...
    def as_four_box(self) -> FourBoxSlice | None:
        """Get the FourBoxSlice if this is a FourBox variant, otherwise None."""
        ...
    def as_hemispheric(self) -> HemisphericSlice | None:
        """Get the HemisphericSlice if this is a Hemispheric variant, otherwise None."""
        ...
    def to_scalar(self) -> float:
        """Convert to a scalar value, aggregating grid values if necessary.

        For Scalar: returns the value directly.
        For FourBox: returns the weighted mean of all 4 regional values.
        For Hemispheric: returns the mean of both hemispheres.
        """
        ...
    def __repr__(self) -> str: ...

class FourBoxSlice:
    @property
    def northern_ocean(self) -> float: ...
    @northern_ocean.setter
    def northern_ocean(self, value: float) -> None: ...
    @property
    def northern_land(self) -> float: ...
    @northern_land.setter
    def northern_land(self, value: float) -> None: ...
    @property
    def southern_ocean(self) -> float: ...
    @southern_ocean.setter
    def southern_ocean(self, value: float) -> None: ...
    @property
    def southern_land(self) -> float: ...
    @southern_land.setter
    def southern_land(self, value: float) -> None: ...
    def __init__(
        self,
        northern_ocean: float = ...,
        northern_land: float = ...,
        southern_ocean: float = ...,
        southern_land: float = ...,
    ) -> None: ...
    @staticmethod
    def uniform(value: float) -> FourBoxSlice: ...
    @staticmethod
    def from_array(values: list[float]) -> FourBoxSlice: ...
    def get(self, region: int) -> float: ...
    def set(self, region: int, value: float) -> None: ...
    def to_array(self) -> Arr: ...
    def to_list(self) -> list[float]: ...
    def to_dict(self) -> dict[str, float]: ...
    def __getitem__(self, index: int) -> float: ...
    def __setitem__(self, index: int, value: float) -> None: ...
    def __len__(self) -> int: ...
    def __repr__(self) -> str: ...

class HemisphericSlice:
    northern: float
    southern: float

    def __init__(
        self,
        northern: float = ...,
        southern: float = ...,
    ) -> None: ...
    @staticmethod
    def uniform(value: float) -> HemisphericSlice: ...
    @staticmethod
    def from_array(values: list[float]) -> HemisphericSlice: ...
    def get(self, region: int) -> float: ...
    def set(self, region: int, value: float) -> None: ...
    def to_array(self) -> Arr: ...
    def to_list(self) -> list[float]: ...
    def to_dict(self) -> dict[str, float]: ...
    def __getitem__(self, index: int) -> float: ...
    def __setitem__(self, index: int, value: float) -> None: ...
    def __len__(self) -> int: ...
    def __repr__(self) -> str: ...

class TimeseriesWindow:
    """Zero-cost view into scalar timeseries data."""

    current_index: int

    def __init__(self, values: list[float], current_index: int) -> None: ...
    def at_start(self) -> float:
        """Get value at start of timestep (index N).

        Use for state variables and exogenous inputs.
        """
        ...
    def at_end(self) -> float | None:
        """Get value at end of timestep (index N+1), if available.

        Use for upstream component outputs. Returns None at last timestep.
        """
        ...
    @property
    def previous(self) -> float:
        """Deprecated: Use at_offset(-1) for consistent timestep-relative access."""
        ...
    def at_offset(self, offset: int) -> float: ...
    def last_n(self, n: int) -> Arr: ...
    def to_array(self) -> Arr: ...
    def __len__(self) -> int: ...
    def __repr__(self) -> str: ...

class FourBoxTimeseriesWindow:
    """View into FourBox grid timeseries data."""

    current_index: int

    def __init__(self, values: list[list[float]], current_index: int) -> None: ...
    def at_start(self, region: int) -> float:
        """Get region value at start of timestep (index N).

        Use for state variables and exogenous inputs.
        """
        ...
    def at_end(self, region: int) -> float | None:
        """Get region value at end of timestep (index N+1), if available.

        Use for upstream component outputs. Returns None at last timestep.
        """
        ...
    def at_start_all(self) -> FourBoxSlice:
        """Get all regional values at start of timestep (index N)."""
        ...
    def at_end_all(self) -> FourBoxSlice | None:
        """Get all regional values at end of timestep (index N+1), if available.

        Returns None at last timestep.
        """
        ...
    @property
    def previous(self) -> FourBoxSlice:
        """Deprecated: Use region(i).at_offset(-1) for consistent access."""
        ...
    def region(self, region: int) -> TimeseriesWindow: ...
    def __len__(self) -> int: ...
    def __repr__(self) -> str: ...

class HemisphericTimeseriesWindow:
    """View into Hemispheric grid timeseries data."""

    current_index: int

    def __init__(self, values: list[list[float]], current_index: int) -> None: ...
    def at_start(self, region: int) -> float:
        """Get region value at start of timestep (index N).

        Use for state variables and exogenous inputs.
        """
        ...
    def at_end(self, region: int) -> float | None:
        """Get region value at end of timestep (index N+1), if available.

        Use for upstream component outputs. Returns None at last timestep.
        """
        ...
    def at_start_all(self) -> HemisphericSlice:
        """Get all regional values at start of timestep (index N)."""
        ...
    def at_end_all(self) -> HemisphericSlice | None:
        """Get all regional values at end of timestep (index N+1), if available.

        Returns None at last timestep.
        """
        ...
    @property
    def previous(self) -> HemisphericSlice:
        """Deprecated: Use region(i).at_offset(-1) for consistent access."""
        ...
    def region(self, region: int) -> TimeseriesWindow: ...
    def __len__(self) -> int: ...
    def __repr__(self) -> str: ...
