#!/usr/bin/env python
#
# Copyright 2025 Xnovo Technology ApS
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an  "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

from typing import Generator, Iterable, Tuple, Union, overload

from numpy._typing import NDArray, _ShapeLike

from ._detail.quaternion import ArrayLike, ArrayNoneLike
from ._detail.types import BoolArrayLike

class Vec3:
    def __init__(
        self,
        x: Union[Vec3, ArrayNoneLike] = None,
        y: ArrayNoneLike = None,
        z: ArrayNoneLike = None,
    ) -> None: ...
    x: ArrayLike
    y: ArrayLike
    z: ArrayLike
    @classmethod
    def from_polar_coordinates(cls, polar: ArrayLike, azimuth: ArrayLike) -> Vec3: ...
    @classmethod
    def like(cls, other: Vec3) -> Vec3: ...
    @classmethod
    def zeros(cls, *args) -> Vec3: ...
    @classmethod
    def rand(cls, *args) -> Vec3: ...
    def __iter__(self) -> Generator[Vec3]: ...
    def __getitem__(self, subs) -> Vec3: ...
    def __setitem__(self, subs, value: Vec3): ...
    def __eq__(self, other: Vec3) -> BoolArrayLike: ...
    def __ne__(self, other: Vec3) -> bool: ...
    def __neg__(self) -> Vec3: ...
    def __mul__(self, other) -> Vec3: ...
    def __rmul__(self, other) -> Vec3: ...
    def __truediv__(self, other) -> Vec3: ...
    def __rtruediv__(self, other) -> Vec3: ...
    def __add__(self, other) -> Vec3: ...
    def __radd__(self, other) -> Vec3: ...
    def __sub__(self, other) -> Vec3: ...
    def __rsub__(self, other) -> Vec3: ...
    def aslist(self) -> list[NDArray]: ...
    def asarray(self) -> NDArray: ...
    def norm(self) -> NDArray: ...
    def normalize(self) -> Vec3: ...
    @classmethod
    def concatenate(cls, tup: Iterable[Vec3], **kwargs) -> Vec3: ...
    @classmethod
    def stack(cls, tup: Iterable[Vec3], **kwargs) -> Vec3: ...
    @classmethod
    def vstack(cls, tup: Iterable[Vec3], **kwargs) -> Vec3: ...
    @classmethod
    def hstack(cls, tup: Iterable[Vec3], **kwargs) -> Vec3: ...
    def reshape(self, *shape: _ShapeLike, **kwargs) -> Vec3: ...
    def flatten(self, **kwargs) -> Vec3: ...
    def ravel(self, **kwargs) -> Vec3: ...
    def transpose(self) -> Vec3: ...
    @property
    def T(self) -> Vec3: ...
    @property
    def ndim(self) -> int: ...
    @property
    def shape(self) -> Tuple[int, ...]: ...
    @property
    def size(self) -> int: ...
    def dot(self, other: Vec3) -> NDArray: ...
    def angle(self, other: Vec3) -> NDArray: ...
    def polar(self) -> NDArray: ...
    def azimuth(self) -> NDArray: ...
    def reflect(self, normal: Vec3) -> Vec3: ...
    def cross(self, other: Vec3) -> Vec3: ...
    def isfinite(self) -> BoolArrayLike: ...
    def round(self, decimals=0) -> Vec3: ...
    def orth(self) -> Vec3: ...
    def antipode(self) -> Vec3: ...
    def __str__(self) -> str: ...  # ?
    def __repr__(self): ...

class Quaternion:
    def __init__(
        self,
        a: Union[Quaternion, ArrayNoneLike] = None,
        b: ArrayNoneLike = None,
        c: ArrayNoneLike = None,
        d: ArrayNoneLike = None,
    ): ...
    a: ArrayLike
    b: ArrayLike
    c: ArrayLike
    d: ArrayLike
    @classmethod
    def concatenate(cls, tup, **kwargs) -> Quaternion: ...
    @classmethod
    def stack(cls, tup, **kwargs) -> Quaternion: ...
    @classmethod
    def vstack(cls, tup, **kwargs) -> Quaternion: ...
    @classmethod
    def hstack(cls, tup, **kwargs) -> Quaternion: ...
    @classmethod
    def like(cls, other: Quaternion) -> Quaternion: ...
    @classmethod
    def rand(cls, *args) -> Quaternion: ...
    @classmethod
    def zeros(cls, *args) -> Quaternion: ...
    @classmethod
    def identity(cls, *args) -> Quaternion: ...
    @classmethod
    def nan(cls, shape) -> Quaternion: ...
    def isnan(self) -> BoolArrayLike: ...
    @classmethod
    def from_axis_angle(cls, axis: Vec3, angle: ArrayLike) -> Quaternion: ...
    @classmethod
    def from_rodrigues(cls, rod: Vec3) -> Quaternion: ...
    @classmethod
    def from_rotation_matrix(cls, rm: NDArray): ...
    @classmethod
    def from_euler_abg(cls, alpha, beta, gamma) -> Quaternion: ...
    @classmethod
    def from_euler_bunge(cls, phi1, Phi, phi2) -> Quaternion: ...
    @classmethod
    def from_rot_x(cls, w) -> Quaternion: ...
    @classmethod
    def from_rot_y(cls, w) -> Quaternion: ...
    @classmethod
    def from_rot_z(cls, w) -> Quaternion: ...
    @classmethod
    def from_euler_zyz(cls, alpha, beta, gamma) -> Quaternion: ...
    @classmethod
    def from_euler_zxz(cls, phi1, Phi, phi2) -> Quaternion: ...
    def __iter__(self) -> Generator[Quaternion]: ...
    def __getitem__(self, subs) -> Quaternion: ...
    def __setitem__(self, subs, value: Quaternion): ...
    def norm(self) -> ArrayLike: ...
    def normalize(self): ...
    def inv(self) -> Quaternion: ...
    def conj(self) -> Quaternion: ...
    def dot(self, other: Quaternion) -> ArrayLike: ...
    def angle(self, other: Union[Quaternion, None] = None) -> ArrayLike: ...
    def axis(self) -> Vec3: ...
    def isfinite(self) -> BoolArrayLike: ...

    # Return corresponding Rodrigues vector
    def as_rodrigues(self) -> Vec3: ...
    def as_rotation_matrix(self) -> NDArray: ...
    def as_euler_zxz(self) -> Tuple[ArrayLike, ArrayLike, ArrayLike]: ...
    def as_euler_zyz(self) -> Tuple[ArrayLike, ArrayLike, ArrayLike]: ...
    def as_euler_bunge(self) -> Tuple[ArrayLike, ArrayLike, ArrayLike]: ...
    def as_euler_abg(self) -> Tuple[ArrayLike, ArrayLike, ArrayLike]: ...
    def aslist(self) -> list[NDArray]: ...
    def asarray(self) -> ArrayLike: ...
    def __eq__(self, other) -> BoolArrayLike: ...
    def __ne__(self, other) -> BoolArrayLike: ...
    def __neg__(self) -> Quaternion: ...
    @overload
    def __mul__(self, other: Vec3) -> Vec3: ...
    @overload
    def __mul__(self, other: Quaternion) -> Quaternion: ...
    # def __mul__(self, other): ...
    def reshape(self, *args: _ShapeLike, **kwargs) -> Quaternion: ...
    def flatten(self, **kwargs) -> Quaternion: ...
    def ravel(self, **kwargs) -> Quaternion: ...
    @property
    def ndim(self) -> int: ...
    @property
    def shape(self) -> Tuple[int, ...]: ...
    @property
    def size(self) -> int: ...
    def __str__(self) -> str: ...
    def __repr__(self): ...
