#ifndef QUADRATIC_HEX_HPP
#define QUADRATIC_HEX_HPP
/**\brief Shape function space for trilinear hexahedron, obtained by a pushforward of the canonical
 * linear (affine) functions. */

#include "moab/ElemEvaluator.hpp"

namespace moab
{

class QuadraticHex
{
  public:
    /** \brief Forward-evaluation of field at parametric coordinates */
    static ErrorCode evalFcn( const double* params, const double* field, const int ndim, const int num_tuples,
                              double* work, double* result );

    /** \brief Reverse-evaluation of parametric coordinates at physical space position */
    static ErrorCode reverseEvalFcn( EvalFcn eval, JacobianFcn jacob, InsideFcn ins, const double* posn,
                                     const double* verts, const int nverts, const int ndim, const double iter_tol,
                                     const double inside_tol, double* work, double* params, int* is_inside );

    /** \brief Evaluate the normal at a specified facet*/
    static ErrorCode normalFcn( const int ientDim, const int facet, const int nverts, const double* verts,
                                double normal[] );

    /** \brief Evaluate the jacobian at a specified parametric position */
    static ErrorCode jacobianFcn( const double* params, const double* verts, const int nverts, const int ndim,
                                  double* work, double* result );

    /** \brief Forward-evaluation of field at parametric coordinates */
    static ErrorCode integrateFcn( const double* field, const double* verts, const int nverts, const int ndim,
                                   const int num_tuples, double* work, double* result );

    /** \brief Function that returns whether or not the parameters are inside the natural space of
     * the element */
    static int insideFcn( const double* params, const int ndim, const double tol );

    static EvalSet eval_set()
    {
        return EvalSet( evalFcn, reverseEvalFcn, normalFcn, jacobianFcn, integrateFcn, NULL, insideFcn );
    }

    static bool compatible( EntityType tp, int numv, EvalSet& eset )
    {
        if( tp == MBHEX && numv == 27 )
        {
            eset = eval_set();
            return true;
        }
        else
            return false;
    }

  protected:
    static double SH( const int i, const double params );
    static double DSH( const int i, const double params );

    /* Preimages of the vertices -- "canonical vertices" -- are known as "corners". */
    static const int corner[27][3];
    static const double gauss[8][2];  // TODO fix me
    static const unsigned int corner_count = 27;
    static const unsigned int gauss_count  = 8;  // TODO fix me

};  // class QuadraticHex

}  // namespace moab

#endif
