import pytest
import numpy as np
from uncertainties import unumpy

from DataChef import ingredient_functions as ing_funcs
from DataChef.ingredient import Ingredient


def test_error_func():
    """
    Creates a line Ingredient with uniform scatter via the error_func keyword, and tests that
    the `eval()` function evaluates properly.
    """
    ing  = Ingredient(ing_funcs.line, "line", m=10, b=-1,
                        error_func=ing_funcs.uniform, error_func_kwargs={'scale':10})

    x = np.linspace(-3,6,4)
    y = ing.eval(x)
    assert [-31, -1, 29, 59] == pytest.approx(unumpy.nominal_values(y))
    assert np.any(unumpy.std_devs(y) != pytest.approx(np.zeros_like(x)))

    y = ing.eval(list(x))
    assert [-31, -1, 29, 59] == pytest.approx(unumpy.nominal_values(y))
    assert np.any(unumpy.std_devs(y) != pytest.approx(np.zeros_like(x)))

def test_yerr_keyword():
    """
    Checks behavior for when you supply the y-errors via the `yerr` keyword in `Ingredient.eval()`,
    that is, this should overwrite any errors generated by the `Ingredient.error_func()`.
    """
    yerr = [.1, .1, .1, .1]
    ing  = Ingredient(ing_funcs.line, "line", m=10, b=-1,
                        error_func=ing_funcs.uniform, error_func_kwargs={'scale':10})

    x = np.linspace(-3,6,4)
    y = ing.eval(x, yerr=yerr)
    print(unumpy.std_devs(y))
    assert [-31, -1, 29, 59] == pytest.approx(unumpy.nominal_values(y))
    assert yerr == pytest.approx(unumpy.std_devs(y))

    y = ing.eval(list(x), yerr=yerr)
    assert [-31, -1, 29, 59] == pytest.approx(unumpy.nominal_values(y))
    assert yerr == pytest.approx(unumpy.std_devs(y))



# def test_rand_seed():
#     """
#     Check that np.random.seed is correctly applied when specifiying a seed
#     """
#     x = np.linspace(-1,100,13)

#     assert np.all(ing_funcs.uniform(x, seed=3) == ing_funcs.uniform(x, seed=3))

# def test_empty_x():
#     """
#     Test the behavior of the eval funchent when given an empty x grid.
#     """
#     ing = Ingredient(ing_funcs.parabola, "para", a=10, b=-1, c=41)

#     assert ing.eval([]) is None
#     assert ing.eval(np.asarray([])) is None