# This file is part of Cantera. See License.txt in the top-level directory or
# at https://cantera.org/license.txt for license and copyright information.

from collections.abc import Sequence
from pathlib import Path
from typing import TypeAlias, TypedDict

from ._types import Array
from .reaction import CustomRate, Reaction
from .solutionbase import _SolutionBase
from .thermo import ThermoPhase
from .units import UnitSystem, _UnitDict

# Avoid fixed options unless we can find a way to support custom extensions:
# _KineticsType: TypeAlias = Literal["none", "bulk", "edge", "surface"]
_KineticsType: TypeAlias = str

_DerivativeSettings = TypedDict(
    "_DerivativeSettings",
    {
        "skip-third-bodies": bool,
        "skip-falloff": bool,
        "rtol-delta": float,
        "skip-coverage-dependence": bool,
        "skip-electrochemistry": bool,
    },
    total=False,
)

class Kinetics(_SolutionBase):
    _custom_rates: list[CustomRate]
    @property
    def kinetics_model(self) -> str: ...
    @property
    def n_total_species(self) -> int: ...
    @property
    def n_reactions(self) -> int: ...
    @property
    def n_phases(self) -> int: ...
    def kinetics_species_index(self, species: str | int, phase: int = 0) -> int: ...
    def kinetics_species_name(self, k: int) -> str: ...
    @property
    def kinetics_species_names(self) -> list[str]: ...
    def reaction(self, i_reaction: int) -> Reaction: ...
    def reactions(self) -> list[Reaction]: ...
    def modify_reaction(self, irxn: int, rxn: Reaction) -> None: ...
    def add_reaction(self, rxn: Reaction) -> None: ...
    def multiplier(self, i_reaction: int) -> float: ...
    def set_multiplier(self, value: float, i_reaction: int = -1) -> None: ...
    def reaction_equations(self, indices: Sequence[int] | None = None) -> list[str]: ...
    def reactant_stoich_coeff(self, k_spec: str | int, i_reaction: int) -> float: ...
    def product_stoich_coeff(self, k_spec: str | int, i_reaction: int) -> float: ...
    @property
    def reactant_stoich_coeffs(self) -> Array: ...
    @property
    def product_stoich_coeffs(self) -> Array: ...
    @property
    def product_stoich_coeffs_reversible(self) -> Array: ...
    @property
    def forward_rates_of_progress(self) -> Array: ...
    @property
    def reverse_rates_of_progress(self) -> Array: ...
    @property
    def net_rates_of_progress(self) -> Array: ...
    @property
    def equilibrium_constants(self) -> Array: ...
    @property
    def forward_rate_constants(self) -> Array: ...
    @property
    def reverse_rate_constants(self) -> Array: ...
    @property
    def creation_rates(self) -> Array: ...
    @property
    def destruction_rates(self) -> Array: ...
    @property
    def net_production_rates(self) -> Array: ...
    @property
    def derivative_settings(self) -> _DerivativeSettings: ...
    @derivative_settings.setter
    def derivative_settings(self, settings: _DerivativeSettings) -> None: ...
    @property
    def forward_rate_constants_ddT(self) -> Array: ...
    @property
    def forward_rate_constants_ddP(self) -> Array: ...
    @property
    def forward_rate_constants_ddC(self) -> Array: ...
    @property
    def forward_rates_of_progress_ddT(self) -> Array: ...
    @property
    def forward_rates_of_progress_ddP(self) -> Array: ...
    @property
    def forward_rates_of_progress_ddC(self) -> Array: ...
    @property
    def forward_rates_of_progress_ddX(self) -> Array: ...
    @property
    def forward_rates_of_progress_ddCi(self) -> Array: ...
    @property
    def reverse_rates_of_progress_ddT(self) -> Array: ...
    @property
    def reverse_rates_of_progress_ddP(self) -> Array: ...
    @property
    def reverse_rates_of_progress_ddC(self) -> Array: ...
    @property
    def reverse_rates_of_progress_ddX(self) -> Array: ...
    @property
    def reverse_rates_of_progress_ddCi(self) -> Array: ...
    @property
    def net_rates_of_progress_ddT(self) -> Array: ...
    @property
    def net_rates_of_progress_ddP(self) -> Array: ...
    @property
    def net_rates_of_progress_ddC(self) -> Array: ...
    @property
    def net_rates_of_progress_ddX(self) -> Array: ...
    @property
    def net_rates_of_progress_ddCi(self) -> Array: ...
    @property
    def creation_rates_ddT(self) -> Array: ...
    @property
    def creation_rates_ddP(self) -> Array: ...
    @property
    def creation_rates_ddC(self) -> Array: ...
    @property
    def creation_rates_ddX(self) -> Array: ...
    @property
    def creation_rates_ddCi(self) -> Array: ...
    @property
    def destruction_rates_ddT(self) -> Array: ...
    @property
    def destruction_rates_ddP(self) -> Array: ...
    @property
    def destruction_rates_ddC(self) -> Array: ...
    @property
    def destruction_rates_ddX(self) -> Array: ...
    @property
    def destruction_rates_ddCi(self) -> Array: ...
    @property
    def net_production_rates_ddT(self) -> Array: ...
    @property
    def net_production_rates_ddP(self) -> Array: ...
    @property
    def net_production_rates_ddC(self) -> Array: ...
    @property
    def net_production_rates_ddX(self) -> Array: ...
    @property
    def net_production_rates_ddCi(self) -> Array: ...
    @property
    def delta_enthalpy(self) -> Array: ...
    @property
    def delta_gibbs(self) -> Array: ...
    @property
    def delta_entropy(self) -> Array: ...
    @property
    def delta_standard_enthalpy(self) -> Array: ...
    @property
    def third_body_concentrations(self) -> Array: ...
    @property
    def delta_standard_gibbs(self) -> Array: ...
    @property
    def delta_standard_entropy(self) -> Array: ...
    @property
    def heat_release_rate(self) -> float: ...
    @property
    def heat_production_rates(self) -> Array: ...

class InterfaceKinetics(Kinetics):
    def advance_coverages(
        self,
        dt: float,
        rtol: float = 1e-7,
        atol: float = 1e-14,
        max_step_size: float = 0.0,
        max_steps: int = 20000,
        max_error_test_failures: int = 7,
    ) -> None: ...
    def advance_coverages_to_steady_state(self) -> None: ...
    def phase_index(self, phase: ThermoPhase | str | int) -> int: ...
    def _phase_slice(self, phase: ThermoPhase | str | int) -> slice[int, int, None]: ...
    def get_creation_rates(self, phase: ThermoPhase | str | int) -> Array: ...
    def get_destruction_rates(self, phase: ThermoPhase | str | int) -> Array: ...
    def get_net_production_rates(self, phase: ThermoPhase | str | int) -> Array: ...
    def interface_current(self, phase: ThermoPhase | str | int) -> float: ...
    def write_yaml(  # type: ignore[override]
        self,
        filename: Path | str,
        phases: Sequence[ThermoPhase] | None = None,
        units: UnitSystem | _UnitDict | None = None,
        precision: int | None = None,
        skip_user_defined: bool | None = None,
    ) -> None: ...
