#include "genEnrichFunctions.h"
#include "genTermApply.h"


#ifndef CONVERTENRICHEDFSPACE_H
#define CONVERTENRICHEDFSPACE_H


template<class T, class T2> class ConvertEnrichedFSpace : public diffTerm<T,0>{
public:
  typedef typename TensorialTraits<T>::ScalarType ScalarType;
  typedef typename TensorialTraits<T>::ValType ValType;
  typedef typename TensorialTraits<T>::GradType GradType;
  typedef typename TensorialTraits<T>::HessType HessType;
  typedef typename ContainerTraits<ValType,0>::Container ContainerValType;
  typedef typename ContainerTraits<GradType,0>::Container ContainerGradType;
  typedef typename ContainerTraits<HessType,0>::Container ContainerHessType;
  typedef typename TensorialTraits<T2>::ScalarType ScalarType2;
  typedef typename TensorialTraits<T2>::ValType ValType2;
  typedef typename TensorialTraits<T2>::GradType GradType2;
  typedef typename TensorialTraits<T2>::HessType HessType2;
  typedef typename ContainerTraits<ValType2,0>::Container ContainerValType2;
  typedef typename ContainerTraits<GradType2,0>::Container ContainerGradType2;
  typedef typename ContainerTraits<HessType2,0>::Container ContainerHessType2;
  static const int Nsp=0;
protected:
  typename diffTerm<ScalarType2,0>::ConstHandle enrichFunctionDerive;
  
public:
  ConvertEnrichedFSpace( const typename diffTerm<ScalarType2,0>::ConstHandle &enrichFunction_) : enrichFunctionDerive(enrichFunction_){}
  
  virtual int getNumKeys(MElement *ele,int k=0) const  {return 0;};
  virtual void getKeys(MElement *ele, std::vector<Dof> &keys, int k=0) const {};
  virtual int getIncidentSpaceTag(int k=0) const { return 0;}
  virtual void get(MElement *ele, int npts, IntPt *GP, ContainerValType &vals) const{
    diffTerm<T,0>::get(ele,npts,GP,vals);
  }
  
  virtual void get(MElement* ele, int npts, IntPt* GP, std::vector<ContainerValType> &vvals) const{
  std::vector< genScalar<ScalarType2> > vvals1(npts); 
  enrichFunctionDerive->get(ele, npts, GP, vvals1);
  for (int i=0;i<npts;++i)
    Apply(vvals1[i],vvals[i],BuildFromOneOp<ScalarType2,ValType>());
  }
  
  virtual void getgradf(MElement *ele, int npts, IntPt *GP, ContainerGradType &grads) const{
    typename genTerm<GradType,0>::ConstHandle GG(Gradient(typename diffTerm<T,0>::ConstHandle(this,NoDelete())));
    GG->get(ele,npts,GP,grads);
  }
  
  virtual void getgradf(MElement *ele, int npts, IntPt *GP, std::vector< ContainerGradType > &vgrads) const{
  std::vector< genScalar<GradType2> > vgrads1(npts);
  enrichFunctionDerive->getgradf(ele, npts,GP, vgrads1);
  for (int i=0;i<npts;++i)
    Apply(vgrads1[i],vgrads[i],BuildFromOneOp<GradType2,GradType>());
  }
  
  virtual void getgradfuvw(MElement *ele, int npts, IntPt *GP, std::vector< ContainerGradType > &vgrads) const {}
  virtual void gethessf(MElement *ele, int npts, IntPt *GP, std::vector< ContainerHessType > &vhesss) const {}
  virtual void gethessf(MElement *ele, int npts, IntPt *GP, ContainerHessType &hesss) const{
    typename genTerm<HessType,0>::ConstHandle HH(Hessian(typename diffTerm<T,0>::ConstHandle(this,NoDelete())));
    HH->get(ele,npts,GP,hesss);
  }
  
  virtual void gethessfuvw(MElement *ele, int npts, IntPt *GP, std::vector< ContainerHessType > &vhesss) const {}

    
};

#endif // CONVERTENRICHEDFSPACE_H
