import pytest
import FIAT
import finat
import numpy as np
from finat.ast import Variable


@pytest.fixture
def cell():
    return FIAT.reference_element.UFCTriangle()


@pytest.fixture
def lagrange(cell):
    return finat.Lagrange(cell, 1)


@pytest.fixture
def kernel_data(lagrange):
    vector_lagrange = finat.VectorFiniteElement(lagrange, 2)

    return finat.KernelData(vector_lagrange, Variable("X"))


@pytest.fixture
def context():
    return {'u': np.array([0.0, 0.6, 0.3])}


def quadrature(cell):
    q = FIAT.quadrature.CollapsedQuadratureTriangleRule(cell, 1)

    points = finat.indices.PointIndex(finat.PointSet(q.get_points()))

    weights = finat.PointSet(q.get_weights())

    return points, weights


@pytest.mark.xfail
def test_basis_evaluation(cell, lagrange, kernel_data):
    points, weights = quadrature(cell)

    recipe = lagrange.basis_evaluation(points, kernel_data, derivative=None)

    result_finat = finat.interpreter.evaluate(recipe, {}, kernel_data)

    result_coffee = finat.coffee_compiler.evaluate(recipe, {}, kernel_data)

    assert(np.abs(result_finat - result_coffee) < 1.e-12).all()


@pytest.mark.xfail
def test_field_evaluation(cell, lagrange, kernel_data, context):
    points, weights = quadrature(cell)

    recipe = lagrange.field_evaluation(Variable("u"), points,
                                       kernel_data, derivative=None)

    result_finat = finat.interpreter.evaluate(recipe, context, kernel_data)

    result_coffee = finat.coffee_compiler.evaluate(recipe, context, kernel_data)

    assert(np.abs(result_finat - result_coffee) < 1.e-12).all()


@pytest.mark.xfail
def test_moment_evaluation(cell, lagrange, kernel_data, context):
    points, weights = quadrature(cell)

    f_recipe = lagrange.field_evaluation(Variable("u"), points,
                                         kernel_data, derivative=None)
    recipe = lagrange.moment_evaluation(f_recipe, weights, points,
                                        kernel_data, pullback=False)

    result_finat = finat.interpreter.evaluate(recipe, context, kernel_data)

    result_coffee = finat.coffee_compiler.evaluate(recipe, context, kernel_data)

    assert(np.abs(result_finat - result_coffee) < 1.e-12).all()

@@ -494,24 +494,32 @@
 drature(cell
+, degree
 ):%0A    q = F
@@ -571,17 +571,22 @@
 e(cell, 
-1
+degree
 )%0A%0A    p
@@ -732,37 +732,70 @@
 %0A%0A%0A@pytest.mark.
-xfail
+parametrize('degree', %5B1, 2, 3, 4, 5%5D)
 %0Adef test_basis_
@@ -832,16 +832,24 @@
 nel_data
+, degree
 ):%0A    p
@@ -872,32 +872,40 @@
  quadrature(cell
+, degree
 )%0A%0A    recipe = 
@@ -1189,37 +1189,70 @@
 %0A%0A%0A@pytest.mark.
-xfail
+parametrize('degree', %5B1, 2, 3, 4, 5%5D)
 %0Adef test_field_
@@ -1290,32 +1290,40 @@
 el_data, context
+, degree
 ):%0A    points, w
@@ -1342,24 +1342,32 @@
 drature(cell
+, degree
 )%0A%0A    recip
@@ -1731,13 +1731,46 @@
 ark.
-xfail
+parametrize('degree', %5B1, 2, 3, 4, 5%5D)
 %0Adef
@@ -1829,16 +1829,24 @@
  context
+, degree
 ):%0A    p
@@ -1877,16 +1877,24 @@
 ure(cell
+, degree
 )%0A%0A    f

Enable lagrange tests across multiple degrees