# Stubs for the SWIG-generated `lal` module used by GWpy.
# Minimal surface area: only symbols referenced by gwpy.utils.lal and related code.

# ruff: noqa: E501, N802, N803, N815

from collections.abc import Iterable
from typing import Generic, TypeVar, overload

import numpy

# Type code constants (integers)
I2_TYPE_CODE: int
I4_TYPE_CODE: int
I8_TYPE_CODE: int
U2_TYPE_CODE: int
U4_TYPE_CODE: int
U8_TYPE_CODE: int
S_TYPE_CODE: int
D_TYPE_CODE: int
C_TYPE_CODE: int
Z_TYPE_CODE: int

# -- Debug ---------------------------

def GetDebugLevel() -> int: ...
def ClobberDebugLevel(level: int) -> None: ...

# -- Cache ---------------------------

class Cache:
    length: int

def CacheGlob(dirname: str, pattern: str) -> Cache: ...

def CacheImport(path: str) -> Cache: ...

def CacheMerge(cache1: Cache, cache2: Cache) -> Cache: ...

# -- Detector-related types ----------

class FrDetector:
    name: str
    prefix: str
    vertexElevation: float
    vertexLatitudeRadians: float
    vertexLongitudeRadians: float
    xArmAltitudeRadians: float
    xArmAzimuthRadians: float
    xArmMidpoint: float
    yArmAltitudeRadians: float
    yArmAzimuthRadians: float
    yArmMidpoint: float

class DetectorContainer:
    frDetector: FrDetector

# CachedDetectors is an iterable of detector-like objects
CachedDetectors: Iterable[DetectorContainer]

# -- Vector --------------------------

class _Vector:
    length: int
    data: numpy.ndarray

_TVector = TypeVar("_TVector", bound=_Vector)

class INT2Vector(_Vector): ...
class INT4Vector(_Vector): ...
class INT8Vector(_Vector): ...
class UINT2Vector(_Vector): ...
class UINT4Vector(_Vector): ...
class UINT8Vector(_Vector): ...
class REAL4Vector(_Vector): ...
class REAL8Vector(_Vector): ...
class COMPLEX8Vector(_Vector): ...
class COMPLEX16Vector(_Vector): ...

def CreateINT2Vector(length: int) -> INT2Vector: ...
def CreateINT4Vector(length: int) -> INT4Vector: ...
def CreateINT8Vector(length: int) -> INT8Vector: ...
def CreateUINT2Vector(length: int) -> UINT2Vector: ...
def CreateUINT4Vector(length: int) -> UINT4Vector: ...
def CreateUINT8Vector(length: int) -> UINT8Vector: ...
def CreateREAL4Vector(length: int) -> REAL4Vector: ...
def CreateREAL8Vector(length: int) -> REAL8Vector: ...
def CreateCOMPLEX8Vector(length: int) -> COMPLEX8Vector: ...
def CreateCOMPLEX16Vector(length: int) -> COMPLEX16Vector: ...

# -- Series --------------------------

class _TimeSeries(Generic[_TVector]):
    data: _TVector
    deltaT: float
    epoch: LIGOTimeGPS
    f0: float
    length: int
    name: str
    sampleUnits: Unit

class INT2TimeSeries(_TimeSeries[INT2Vector]): ...
class INT4TimeSeries(_TimeSeries[INT4Vector]): ...
class INT8TimeSeries(_TimeSeries[INT8Vector]): ...
class UINT2TimeSeries(_TimeSeries[UINT2Vector]): ...
class UINT4TimeSeries(_TimeSeries[UINT4Vector]): ...
class UINT8TimeSeries(_TimeSeries[UINT8Vector]): ...
class REAL4TimeSeries(_TimeSeries[REAL4Vector]): ...
class REAL8TimeSeries(_TimeSeries[REAL8Vector]): ...
class COMPLEX8TimeSeries(_TimeSeries[COMPLEX8Vector]): ...
class COMPLEX16TimeSeries(_TimeSeries[COMPLEX16Vector]): ...

def CreateINT2TimeSeries(
    name: str | None, epoch: LIGOTimeGPS, f0: float,
    deltaT: float, sampleUnits: Unit, length: int,
) -> INT2TimeSeries: ...

def CreateINT4TimeSeries(
    name: str | None, epoch: LIGOTimeGPS, f0: float,
    deltaT: float, sampleUnits: Unit, length: int,
) -> INT4TimeSeries: ...

def CreateINT8TimeSeries(
    name: str | None, epoch: LIGOTimeGPS, f0: float,
    deltaT: float, sampleUnits: Unit, length: int,
) -> INT8TimeSeries: ...

def CreateUINT2TimeSeries(
    name: str | None, epoch: LIGOTimeGPS, f0: float,
    deltaT: float, sampleUnits: Unit, length: int,
) -> UINT2TimeSeries: ...

def CreateUINT4TimeSeries(
    name: str | None, epoch: LIGOTimeGPS, f0: float,
    deltaT: float, sampleUnits: Unit, length: int,
) -> UINT4TimeSeries: ...

def CreateUINT8TimeSeries(
    name: str | None, epoch: LIGOTimeGPS, f0: float,
    deltaT: float, sampleUnits: Unit, length: int,
) -> UINT8TimeSeries: ...

def CreateREAL4TimeSeries(
    name: str | None, epoch: LIGOTimeGPS, f0: float,
    deltaT: float, sampleUnits: Unit, length: int,
) -> REAL4TimeSeries: ...

def CreateREAL8TimeSeries(
    name: str | None, epoch: LIGOTimeGPS, f0: float,
    deltaT: float, sampleUnits: Unit, length: int,
) -> REAL8TimeSeries: ...

def CreateCOMPLEX8TimeSeries(
    name: str | None, epoch: LIGOTimeGPS, f0: float,
    deltaT: float, sampleUnits: Unit, length: int,
) -> COMPLEX8TimeSeries: ...

def CreateCOMPLEX16TimeSeries(
    name: str | None, epoch: LIGOTimeGPS, f0: float,
    deltaT: float, sampleUnits: Unit, length: int,
) -> COMPLEX16TimeSeries: ...

class _FrequencySeries(Generic[_TVector]):
    data: _TVector
    deltaF: float
    epoch: LIGOTimeGPS
    f0: float
    length: int
    name: str
    sampleUnits: Unit

class INT2FrequencySeries(_FrequencySeries[INT2Vector]): ...
class INT4FrequencySeries(_FrequencySeries[INT4Vector]): ...
class INT8FrequencySeries(_FrequencySeries[INT8Vector]): ...
class UINT2FrequencySeries(_FrequencySeries[UINT2Vector]): ...
class UINT4FrequencySeries(_FrequencySeries[UINT4Vector]): ...
class UINT8FrequencySeries(_FrequencySeries[UINT8Vector]): ...
class REAL4FrequencySeries(_FrequencySeries[REAL4Vector]): ...
class REAL8FrequencySeries(_FrequencySeries[REAL8Vector]): ...
class COMPLEX8FrequencySeries(_FrequencySeries[COMPLEX8Vector]): ...
class COMPLEX16FrequencySeries(_FrequencySeries[COMPLEX16Vector]): ...

def CreateINT2FrequencySeries(
    name: str | None, f0: float,
    deltaF: float, sampleUnits: Unit, length: int,
) -> INT2FrequencySeries: ...

def CreateINT4FrequencySeries(
    name: str | None, f0: float,
    deltaF: float, sampleUnits: Unit, length: int,
) -> INT4FrequencySeries: ...

def CreateINT8FrequencySeries(
    name: str | None, f0: float,
    deltaF: float, sampleUnits: Unit, length: int,
) -> INT8FrequencySeries: ...

def CreateUINT2FrequencySeries(
    name: str | None, f0: float,
    deltaF: float, sampleUnits: Unit, length: int,
) -> UINT2FrequencySeries: ...

def CreateUINT4FrequencySeries(
    name: str | None, f0: float,
    deltaF: float, sampleUnits: Unit, length: int,
) -> UINT4FrequencySeries: ...

def CreateUINT8FrequencySeries(
    name: str | None, f0: float,
    deltaF: float, sampleUnits: Unit, length: int,
) -> UINT8FrequencySeries: ...

def CreateREAL4FrequencySeries(
    name: str | None, f0: float,
    deltaF: float, sampleUnits: Unit, length: int,
) -> REAL4FrequencySeries: ...

def CreateREAL8FrequencySeries(
    name: str | None, f0: float,
    deltaF: float, sampleUnits: Unit, length: int,
) -> REAL8FrequencySeries: ...

def CreateCOMPLEX8FrequencySeries(
    name: str | None, f0: float,
    deltaF: float, sampleUnits: Unit, length: int,
) -> COMPLEX8FrequencySeries: ...

def CreateCOMPLEX16FrequencySeries(
    name: str | None, f0: float,
    deltaF: float, sampleUnits: Unit, length: int,
) -> COMPLEX16FrequencySeries: ...

# -- Window --------------------------

class _Window(Generic[_TVector]):
    data: _TVector
    sum: float
    sumofsquares: float

class REAL4Window(_Window[REAL4Vector]): ...
class REAL8Window(_Window[REAL8Vector]): ...

def CreateNamedREAL4Window(windowName: str, length: int) -> REAL4Window: ...
def CreateNamedREAL8Window(windowName: str, length: int) -> REAL8Window: ...

# -- FFTPlan -------------------------

class REAL4FFTPlan: ...
class REAL8FFTPlan: ...
class COMPLEX8FFTPlan: ...
class COMPLEX16FFTPlan: ...

def CreateREAL4FFTPlan(size: int, fwdflg: int, measurelvl: int) -> REAL4FFTPlan: ...
def CreateREAL8FFTPlan(size: int, fwdflg: int, measurelvl: int) -> REAL8FFTPlan: ...
def CreateCOMPLEX8FFTPlan(size: int, fwdflg: int, measurelvl: int) -> COMPLEX8FFTPlan: ...
def CreateCOMPLEX16FFTPlan(size: int, fwdflg: int, measurelvl: int) -> COMPLEX16FFTPlan: ...

# Average spectrum functions / types used by the spectral glue layer
class REAL8AverageSpectrumWelch: ...
class REAL8AverageSpectrumMedian: ...
class REAL8AverageSpectrumMedianMean: ...

# -- Sequence ------------------------

def CreateINT2Sequence(length: int) -> INT2Vector: ...
def CreateINT4Sequence(length: int) -> INT4Vector: ...
def CreateINT8Sequence(length: int) -> INT8Vector: ...
def CreateUINT2Sequence(length: int) -> UINT2Vector: ...
def CreateUINT4Sequence(length: int) -> UINT4Vector: ...
def CreateUINT8Sequence(length: int) -> UINT8Vector: ...
def CreateREAL8Sequence(length: int) -> REAL8Vector: ...
def CreateCOMPLEX8Sequence(length: int) -> COMPLEX8Vector: ...
def CreateCOMPLEX16Sequence(length: int) -> COMPLEX16Vector: ...

# -- Time ----------------------------

# LIGO time struct
class LIGOTimeGPS:
    gpsSeconds: int
    gpsNanoSeconds: int

    @overload
    def __init__(self) -> None: ...
    @overload
    def __init__(self, new: float | LIGOTimeGPS | str) -> None: ...
    @overload
    def __init__(self, seconds: int, nanoseconds: int) -> None: ...

    def __float__(self) -> float: ...
    def __int__(self) -> int: ...

    # equality: accept any object (Python semantics)
    def __eq__(self, other: object) -> bool: ...
    def __ne__(self, other: object) -> bool: ...

    # ordering comparisons with other times or numeric offsets
    def __lt__(self, other: LIGOTimeGPS | float) -> bool: ...
    def __le__(self, other: LIGOTimeGPS | float) -> bool: ...
    def __gt__(self, other: LIGOTimeGPS | float) -> bool: ...
    def __ge__(self, other: LIGOTimeGPS | float) -> bool: ...

    # arithmetic: addition/subtraction with another time or numeric offset
    def __add__(self, other: LIGOTimeGPS | float) -> LIGOTimeGPS: ...
    def __radd__(self, other: float) -> LIGOTimeGPS: ...
    def __sub__(self, other: LIGOTimeGPS | float) -> LIGOTimeGPS: ...
    def __rsub__(self, other: float) -> LIGOTimeGPS: ...

    # unary
    def __neg__(self) -> LIGOTimeGPS: ...
    def __pos__(self) -> LIGOTimeGPS: ...

# Unit representation used by LAL. The real C struct exposes arrays of
# integers; expose as mutable sequences for simple indexed assignment.
class Unit:
    unitNumerator: list[int]
    unitDenominatorMinusOne: list[int]
    powerOfTen: int
    def __init__(self, spec: str | None = None) -> None: ...

DimensionlessUnit: Unit
MeterUnit: Unit
StrainUnit: Unit
