import numpy as np

from ..utils.constants import kB


class _MAScalibration:
    type = 'Other'
    name = 'MAS temperature'
    equation = ''
    params = ['Slope', 'Offset']

    @staticmethod
    def func(p, x):
        realt = p[0] * x + p[1]
        return 1250 - 3.81194e-6 * np.sqrt(1.47663e17 - 1.32344e14 * realt)


class VFT:
    r"""
    Calculates Vogel-Fulcher-Tammann

    .. math::
        f(x) = \tau_0 \exp\left(\frac{B}{x-T_0}\right)
    """
    type = 'Temperature'
    name = 'VFT'
    equation = r'\tau_{0} exp(B/(x-T_{0}))'
    params = [r'\tau_{0}', 'B', 'T_{0}']
    choices = [('Temperature', 'invt',  {'T': 't', '1/T': 'invt', '1000/T': 'invt1000'})]
    bounds = [(0, None), (None, None), (0, None)]

    @staticmethod
    def func(x, tau0, b, t0, invt='invt1000'):
        if invt == 'invt':
            x = 1./x
        elif invt == 'invt1000':
            x = 1000. / x

        return tau0 * np.exp(b / (x-t0))


class Arrhenius:
    type = 'Temperature'
    name = 'Arrhenius'
    equation = r'\tau_{0} exp(E_{A}/(k_{B} x))'
    params = [r'\tau_{0}', 'E_{A}']
    choices = [('Temperature', 'invt', {'T': 't', '1/T': 'invt', '1000/T': 'invt1000'})]
    bounds = [(0, None), (None, None), (0, None)]

    @staticmethod
    def func(x, tau0, ea, invt='invt1000'):
        if invt == 'invt':
            x = 1./x
        elif invt == 'invt1000':
            x = 1000. / x

        return tau0 * np.exp(ea / (kB*x))


class Ecoop:
    name = 'Roessler-Ding'
    type = 'Temperature'
    equation = r'\tau_{\infty}exp[E_{\infty}/T(1+exp(-\mu((T-T_{A})/E_{\infty})))]'
    params = [r'\tau_{\infty}', r'E_{\infty}', r'\mu', 'T_{A}']
    choices = [('Temperature', 'invt', {'T': 't', '1000/T': 'invt1000'})]

    @staticmethod
    def func(x, tau0, e_infty, mu, ta, invt='invt1000'):
        if invt == 'invt1000':
            x = 1000. / x

        ec = e_infty * np.exp(-mu * (x - ta) / e_infty)

        return tau0 * np.exp((e_infty + ec) / x)
