# cython: cpow=True

from . cimport sf_error
from ._cephes cimport poch

cdef extern from "specfun_wrappers.h":
    double pmv_wrap(double, double, double) nogil

from ._complexstuff cimport *
from libc.math cimport cos, sqrt, fabs, NAN, M_PI
from libc.stdlib cimport abs

cdef inline double complex sph_harmonic(int m, int n, double theta, double phi) noexcept nogil:
    cdef double x, prefactor
    cdef double complex val
    cdef int mp
    x = cos(phi)
    if abs(m) > n :
        sf_error.error("sph_harm", sf_error.ARG, "m should not be greater than n")
        return NAN
    if n < 0:
        sf_error.error("sph_harm", sf_error.ARG, "n should not be negative")
        return NAN
    if m < 0:
        mp = -m
        prefactor = (-1)**mp * poch(n + mp + 1, -2 * mp)
    else:
        mp = m
    val = pmv_wrap(mp, n, x)
    if  m < 0:
        val *= prefactor
    val *= sqrt((2*n + 1) / 4.0 / M_PI)
    val *= sqrt(poch(n + m + 1, -2 * m))
    val *= zexp(1j * m * theta)
    return val
