"""

"""
from __future__ import annotations

import numpy as np
#import fit2x


def convolve_lifetime_spectrum(
        irf: np.ndarray,
        decay: np.ndarray,
        lifetime_spectrum: np.ndarray = None,
        stop: int = -1,
        time_axis: np.ndarray = None,
        constant_dt: bool = True,
        dt: float = None,
        periodic: bool = False,
        period: float = 100.,
        start: int = 0,
        verbose: bool = False
) -> None:
    """Convolves a fluorescence lifetime spectrum with an instrumnet response
    function

    A the pre-allocated array is filled with a fluorescence intensity decay convolved
    with an instrumental response function that can be periodic.

    This function calculates a fluorescence intensity decay that is convolved
    with an instrumnet response function (IRF). The fluorescence intensity decay
    is specified by its fluorescence lifetime spectrum, i.e., an interleaved array
    containing fluorescence lifetimes with corresponding amplitudes.

    :param decay: numpy-array This array filled with the values of the computed
    fluorescence intensity decay
    :param lifetime_spectrum: interleaved vector of amplitudes and fluorescence
    lifetimes
    :param irf: the instrument response function
    :param stop: convolution stop channel (the index on the time-axis)
    :param time_axis: the time-axis of the decay

    Example
    -------
    >>> import scipy.stats
    >>> time_axis = np.linspace(0, 50, 2048)
    >>> irf_position = 5.0
    >>> irf_width = 1.0
    >>> irf = scipy.stats.norm.pdf(time_axis, loc=irf_position, scale=irf_width)
    >>> lifetime_spectrum = np.array([0.8, 1.1, 0.2, 4.0])
    >>> decay = np.zeros_like(time_axis)
    >>> convolve_lifetime_spectrum(decay, lifetime_spectrum=lifetime_spectrum, irf=irf, time_axis=time_axis)

    """
    if constant_dt:
        if dt is None:
            dt = time_axis[1] - time_axis[0]
        if periodic:
            fit2x.fconv_per_cs(
                fit=decay,
                irf=irf,
                stop=stop,
                x=lifetime_spectrum,
                period=period,
                conv_stop=stop,
                dt=dt
            )
        else:
            fit2x.fconv(
                x=lifetime_spectrum,
                fit=decay,
                irf=irf,
                start=start,
                stop=stop,
                dt=dt
            )
    else:
        if verbose:
            dt = np.diff(time_axis)
        fit2x.fconv_per_cs_time_axis(
            model=decay,
            time_axis=time_axis,
            instrument_response_function=irf,
            lifetime_spectrum=lifetime_spectrum,
            convolution_start=start,
            convolution_stop=stop,
            use_amplitude_threshold=False,
            amplitude_threshold=1e10,
            period=period
        )
    if verbose:
        print("------------")
        print("Convolution:")
        print("Lifetimes: %s" % lifetime_spectrum)
        print("dt: %s" % dt)
        print("Stop: %s" % stop)
        print("dt: %s" % dt)


def convolve_decay_curve(
        irf: np.ndarray,
        decay: np.ndarray,
        decay_convolved: np.ndarray,
        start: int = 0,
        stop: int = None
):
    """Convolves a decay curve with an instrument response function

    :param irf:
    :param decay:
    :param decay_convolved:
    :param start:
    :param stop:
    :return:
    """
    if stop is None:
        stop = min(len(irf), len(decay)) - 1
    fit2x.sconv(
        fit=decay_convolved,
        model=decay,
        irf=irf,
        start=start,
        stop=stop
    )


def shift(
        obj: np.ndarray,
        shifted_obj: np.ndarray,
        index: float
) -> None:
    """Shifts an array by a number.

    This function shifts an input array by a floating number of indices. For
    non-integer shifts the values in the output array are linearly interpolated.

    :param obj: numpy-array This array is in TCSPC typically the instrumnet
    response function (IRF).
    :param shifted_obj: this array is modified in-place to contain the shifted
    object.
    :param index: float the number of indices the input array is shifted. In TCSPC this
    is the number of channels

    Examples
    --------
    >>> import scipy.stats
    >>> time_axis = np.linspace(4.5, 5.5, 16)
    >>> irf_position = 5.0
    >>> irf_width = 0.25
    >>> irf = scipy.stats.norm.pdf(time_axis, loc=irf_position, scale=irf_width)
    >>> irf_shift = np.empty_like(irf)
    >>> time_shift = 0.5
    >>> fit2x.shift_lamp(irf, irf_shift, time_shift)
    >>> irf_shift
    array([0.28561886, 0.44980189, 0.66053707, 0.90452776, 1.15505166,
       1.37543629, 1.52736396, 1.58164736, 1.52736396, 1.37543629,
       1.15505166, 0.90452776, 0.66053707, 0.44980189, 0.28561886,
       0.        ])
    """
    fit2x.shift_lamp(obj, shifted_obj, index)
