from collections.abc import Callable, Mapping
from pprint import pprint as show
from typing import Any, Final, Never, TypeAlias, TypeVar, overload
from typing import Literal as L

from _typeshed import FileDescriptorOrPath

from .cfuncs import errmess

__all__ = [
    "applyrules",
    "containscommon",
    "containsderivedtypes",
    "debugcapi",
    "dictappend",
    "errmess",
    "gentitle",
    "get_f2py_modulename",
    "getargs2",
    "getcallprotoargument",
    "getcallstatement",
    "getdimension",
    "getfortranname",
    "getpymethoddef",
    "getrestdoc",
    "getuseblocks",
    "getusercode",
    "getusercode1",
    "hasbody",
    "hascallstatement",
    "hascommon",
    "hasexternals",
    "hasinitvalue",
    "hasnote",
    "hasresultnote",
    "isallocatable",
    "isarray",
    "isarrayofstrings",
    "isattr_value",
    "ischaracter",
    "ischaracter_or_characterarray",
    "ischaracterarray",
    "iscomplex",
    "iscomplexarray",
    "iscomplexfunction",
    "iscomplexfunction_warn",
    "iscstyledirective",
    "isdouble",
    "isdummyroutine",
    "isexternal",
    "isfunction",
    "isfunction_wrap",
    "isint1",
    "isint1array",
    "isinteger",
    "isintent_aux",
    "isintent_c",
    "isintent_callback",
    "isintent_copy",
    "isintent_dict",
    "isintent_hide",
    "isintent_in",
    "isintent_inout",
    "isintent_inplace",
    "isintent_nothide",
    "isintent_out",
    "isintent_overwrite",
    "islogical",
    "islogicalfunction",
    "islong_complex",
    "islong_double",
    "islong_doublefunction",
    "islong_long",
    "islong_longfunction",
    "ismodule",
    "ismoduleroutine",
    "isoptional",
    "isprivate",
    "isrequired",
    "isroutine",
    "isscalar",
    "issigned_long_longarray",
    "isstring",
    "isstring_or_stringarray",
    "isstringarray",
    "isstringfunction",
    "issubroutine",
    "issubroutine_wrap",
    "isthreadsafe",
    "isunsigned",
    "isunsigned_char",
    "isunsigned_chararray",
    "isunsigned_long_long",
    "isunsigned_long_longarray",
    "isunsigned_short",
    "isunsigned_shortarray",
    "isvariable",
    "l_and",
    "l_not",
    "l_or",
    "outmess",
    "process_f2cmap_dict",
    "replace",
    "show",
    "stripcomma",
    "throw_error",
]

###

_VT = TypeVar("_VT")
_RT = TypeVar("_RT")

_Var: TypeAlias = Mapping[str, list[str]]
_ROut: TypeAlias = Mapping[str, str]
_F2CMap: TypeAlias = Mapping[str, Mapping[str, str]]

_Bool: TypeAlias = bool | L[0, 1]
_Intent: TypeAlias = L[
    "INTENT_IN",
    "INTENT_OUT",
    "INTENT_INOUT",
    "INTENT_C",
    "INTENT_CACHE",
    "INTENT_HIDE",
    "INTENT_INPLACE",
    "INTENT_ALIGNED4",
    "INTENT_ALIGNED8",
    "INTENT_ALIGNED16",
    "OPTIONAL",
]

###

isintent_dict: dict[Callable[[_Var], _Bool], _Intent]

class F2PYError(Exception): ...

class throw_error:
    mess: Final[str]
    def __init__(self, /, mess: str) -> None: ...
    def __call__(self, /, var: _Var) -> Never: ...  # raises F2PYError

#
def l_and(*f: tuple[str, Callable[[_VT], _RT]]) -> Callable[[_VT], _RT]: ...
def l_or(*f: tuple[str, Callable[[_VT], _RT]]) -> Callable[[_VT], _RT]: ...
def l_not(f: tuple[str, Callable[[_VT], _RT]]) -> Callable[[_VT], _RT]: ...

#
def outmess(t: str) -> None: ...
def debugcapi(var: _Var) -> bool: ...

#
def hasinitvalue(var: _Var | str) -> bool: ...
def hasnote(var: _Var | str) -> bool: ...
def ischaracter(var: _Var) -> bool: ...
def ischaracterarray(var: _Var) -> bool: ...
def ischaracter_or_characterarray(var: _Var) -> bool: ...
def isstring(var: _Var) -> bool: ...
def isstringarray(var: _Var) -> bool: ...
def isstring_or_stringarray(var: _Var) -> bool: ...
def isarray(var: _Var) -> bool: ...
def isarrayofstrings(var: _Var) -> bool: ...
def isscalar(var: _Var) -> bool: ...
def iscomplex(var: _Var) -> bool: ...
def islogical(var: _Var) -> bool: ...
def isinteger(var: _Var) -> bool: ...
def isint1(var: _Var) -> bool: ...
def isint1array(var: _Var) -> bool: ...
def islong_long(var: _Var) -> _Bool: ...
def isunsigned(var: _Var) -> _Bool: ...
def isunsigned_char(var: _Var) -> _Bool: ...
def isunsigned_chararray(var: _Var) -> bool: ...
def isunsigned_short(var: _Var) -> _Bool: ...
def isunsigned_shortarray(var: _Var) -> bool: ...
def isunsigned_long_long(var: _Var) -> _Bool: ...
def isunsigned_long_longarray(var: _Var) -> bool: ...
def issigned_long_longarray(var: _Var) -> bool: ...
def isdouble(var: _Var) -> _Bool: ...
def islong_double(var: _Var) -> _Bool: ...
def islong_complex(var: _Var) -> _Bool: ...
def iscomplexarray(var: _Var) -> bool: ...
def isallocatable(var: _Var) -> bool: ...
def isattr_value(var: _Var) -> bool: ...
def isoptional(var: _Var) -> bool: ...
def isexternal(var: _Var) -> bool: ...
def isrequired(var: _Var) -> bool: ...
def isprivate(var: _Var) -> bool: ...
def isvariable(var: _Var) -> bool: ...
def isintent_in(var: _Var) -> _Bool: ...
def isintent_inout(var: _Var) -> bool: ...
def isintent_out(var: _Var) -> bool: ...
def isintent_hide(var: _Var) -> bool: ...
def isintent_nothide(var: _Var) -> bool: ...
def isintent_c(var: _Var) -> bool: ...
def isintent_cache(var: _Var) -> bool: ...
def isintent_copy(var: _Var) -> bool: ...
def isintent_overwrite(var: _Var) -> bool: ...
def isintent_callback(var: _Var) -> bool: ...
def isintent_inplace(var: _Var) -> bool: ...
def isintent_aux(var: _Var) -> bool: ...

#
def containsderivedtypes(rout: _ROut) -> L[0, 1]: ...
def containscommon(rout: _ROut) -> _Bool: ...
def hasexternals(rout: _ROut) -> bool: ...
def hasresultnote(rout: _ROut) -> _Bool: ...
def hasbody(rout: _ROut) -> _Bool: ...
def hascommon(rout: _ROut) -> bool: ...
def hasderivedtypes(rout: _ROut) -> bool: ...
def hascallstatement(rout: _ROut) -> bool: ...
def isroutine(rout: _ROut) -> bool: ...
def ismodule(rout: _ROut) -> bool: ...
def ismoduleroutine(rout: _ROut) -> bool: ...
def issubroutine(rout: _ROut) -> bool: ...
def issubroutine_wrap(rout: _ROut) -> _Bool: ...
def isfunction(rout: _ROut) -> bool: ...
def isfunction_wrap(rout: _ROut) -> _Bool: ...
def islogicalfunction(rout: _ROut) -> _Bool: ...
def islong_longfunction(rout: _ROut) -> _Bool: ...
def islong_doublefunction(rout: _ROut) -> _Bool: ...
def iscomplexfunction(rout: _ROut) -> _Bool: ...
def iscomplexfunction_warn(rout: _ROut) -> _Bool: ...
def isstringfunction(rout: _ROut) -> _Bool: ...
def isthreadsafe(rout: _ROut) -> bool: ...
def isdummyroutine(rout: _ROut) -> _Bool: ...
def iscstyledirective(f2py_line: str) -> bool: ...

# .
def getdimension(var: _Var) -> list[Any] | None: ...
def getfortranname(rout: _ROut) -> str: ...
def getmultilineblock(rout: _ROut, blockname: str, comment: _Bool = 1, counter: int = 0) -> str | None: ...
def getcallstatement(rout: _ROut) -> str | None: ...
def getcallprotoargument(rout: _ROut, cb_map: dict[str, str] = {}) -> str: ...
def getusercode(rout: _ROut) -> str | None: ...
def getusercode1(rout: _ROut) -> str | None: ...
def getpymethoddef(rout: _ROut) -> str | None: ...
def getargs(rout: _ROut) -> tuple[list[str], list[str]]: ...
def getargs2(rout: _ROut) -> tuple[list[str], list[str]]: ...
def getrestdoc(rout: _ROut) -> str | None: ...

#
def gentitle(name: str) -> str: ...
def stripcomma(s: str) -> str: ...
@overload
def replace(str: str, d: list[str], defaultsep: str = "") -> list[str]: ...
@overload
def replace(str: list[str], d: str, defaultsep: str = "") -> list[str]: ...
@overload
def replace(str: str, d: str, defaultsep: str = "") -> str: ...

#
def dictappend(rd: Mapping[str, object], ar: Mapping[str, object] | list[Mapping[str, object]]) -> dict[str, Any]: ...
def applyrules(rules: Mapping[str, object], d: Mapping[str, object], var: _Var = {}) -> dict[str, Any]: ...

#
def get_f2py_modulename(source: FileDescriptorOrPath) -> str: ...
def getuseblocks(pymod: Mapping[str, Mapping[str, Mapping[str, str]]]) -> list[str]: ...
def process_f2cmap_dict(
    f2cmap_all: _F2CMap,
    new_map: _F2CMap,
    c2py_map: _F2CMap,
    verbose: bool = False,
) -> tuple[dict[str, dict[str, str]], list[str]]: ...
