#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_export.h"

#include "moab/ElemEvaluator.hpp"

namespace moab 
{
    
class MOAB_EXPORT 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

} // moab namespace

#endif

