"""Shared base classes and constants for airfoil thickness relations."""

from abc import ABC, abstractmethod

import numpy as np

from buffalo_wings.internal.numeric import as_float_array
from buffalo_wings.type_aliases import FloatArray, FloatInput

MAX_THICKNESS_INDEX_LIMIT = 100
LEADING_EDGE_INDEX_MIN = 1
LEADING_EDGE_INDEX_MAX = 10
MAX_THICKNESS_LOCATION_MIN = 1
MAX_THICKNESS_LOCATION_MAX = 10
CLASSIC_LEADING_EDGE_INDEX_THRESHOLD = 9
OPEN_TRAILING_EDGE_THICKNESS = 0.002
OPEN_MODIFIED_TRAILING_EDGE_THICKNESS = 0.02
LEADING_EDGE_RADIUS_SCALE = 25 * 0.08814961


class Thickness(ABC):
    """
    Base class for thickness distribution.

    The thickness will have a parameterization from 0 to 1 and is not
    defined outside of that range. This parameterization should be chosen so
    that all derivatives are finite over the entire parameterization range.
    """

    @abstractmethod
    def discontinuities(self) -> list[float]:
        """
        Return the locations of any discontinuities in the thickness.

        Returns
        -------
        List[float]
            Parametrics coordinates of any discontinuities.
        """

    @abstractmethod
    def max_thickness_parameter(self) -> float:
        """
        Return parameter coordinate of maximum thickness.

        Returns
        -------
        float
            Parameter coordinate of maximum thickness.
        """

    @abstractmethod
    def delta(self, t: FloatInput) -> FloatArray:
        """
        Return the thickness at specified parameter location.

        Parameters
        ----------
        t : numpy.ndarray
            Parameter location of interest.

        Returns
        -------
        numpy.ndarray
            Thickness at specified parameter.
        """

    @abstractmethod
    def delta_t(self, t: FloatInput) -> FloatArray:
        """
        Return first derivative of thickness at specified parameter location.

        Parameters
        ----------
        t : numpy.ndarray
            Parameter location of interest.

        Returns
        -------
        numpy.ndarray
            First derivative of thickness at specified parameter.
        """

    @abstractmethod
    def delta_tt(self, t: FloatInput) -> FloatArray:
        """
        Return second derivative of thickness at specified parameter location.

        Parameters
        ----------
        t : numpy.ndarray
            Parameter location of interest.

        Returns
        -------
        numpy.ndarray
            Second derivative of thickness at specified parameter.
        """


class NoThickness(Thickness):
    """
    Representation of the case where there is no thickness.

    This thickness distribution evaluates to zero everywhere.
    """

    def __init__(self) -> None:
        """
        Initialize the zero-thickness representation.

        Returns
        -------
        None
            This initializer stores no additional state.
        """
        pass

    def discontinuities(self) -> list[float]:  # noqa: PLR6301
        """
        Return the locations of any discontinuities in the thickness.

        Returns
        -------
        List[float]
            Parametric coordinates of any discontinuities.
        """
        return []

    def max_thickness_parameter(self) -> float:  # noqa: PLR6301
        """
        Return parameter coordinate of maximum thickness.

        Returns
        -------
        float
            Parameter coordinate of maximum thickness.
        """
        return 0.0

    def delta(self, t: FloatInput) -> FloatArray:  # noqa: PLR6301
        """
        Return the thickness at specified parameter location.

        Parameters
        ----------
        t : numpy.ndarray
            Parameter location of interest. Equal to the square root of the
            desired chord location.

        Returns
        -------
        numpy.ndarray
            Thickness at specified parameter.
        """
        t = as_float_array(t)
        return np.zeros_like(t)

    def delta_t(self, t: FloatInput) -> FloatArray:  # noqa: PLR6301
        """
        Return first derivative of thickness at specified parameter location.

        Parameters
        ----------
        t : numpy.ndarray
            Parameter location of interest. Equal to the square root of the
            desired chord location.

        Returns
        -------
        numpy.ndarray
            First derivative of thickness at specified parameter.
        """
        t = as_float_array(t)
        return np.zeros_like(t)

    def delta_tt(self, t: FloatInput) -> FloatArray:  # noqa: PLR6301
        """
        Return second derivative of thickness at specified parameter location.

        Parameters
        ----------
        t : numpy.ndarray
            Parameter location of interest. Equal to the square root of the
            desired chord location.

        Returns
        -------
        numpy.ndarray
            Second derivative of thickness at specified parameter.
        """
        t = as_float_array(t)
        return np.zeros_like(t)
