#include "genFSpace.h"
#include "genGroupOfElements.h"

#ifndef RESTRICTEDFILTEREDFSPACE_H
#define RESTRICTEDFILTEREDFSPACE_H

template<class T> class RestrictedFilteredFSpace : public genFSpace<T>{
  
  public:
  typedef typename TensorialTraits<T>::ValType ValType;
  typedef typename TensorialTraits<T>::GradType GradType;
  typedef typename TensorialTraits<T>::HessType HessType;
  typedef typename ContainerTraits<ValType,1>::Container ContainerValType;
  typedef typename ContainerTraits<GradType,1>::Container ContainerGradType;
  typedef typename ContainerTraits<HessType,1>::Container ContainerHessType;
  static const int Nsp=1;
protected:
    typename genFSpace<T>::ConstHandle BaseFS;
    typename genFSpace<T>::ConstHandle FilteredFS;
    const genFilterElement *FilterEle;

    
public:
  RestrictedFilteredFSpace(const typename genFSpace<T>::ConstHandle &BaseFS_, const typename genFSpace<T>::ConstHandle &FilteredFS_,
			   const genFilterElement *FilterEle_) : BaseFS(BaseFS_) , FilteredFS(FilteredFS_),  FilterEle(FilterEle_){}
    

  virtual int getNumKeys(MElement *ele, int k=0) const{
    if((*FilterEle)(ele))
      return FilteredFS->getNumKeys(ele);
    else
      return BaseFS->getNumKeys(ele);
  }
  
  virtual void getKeys(MElement *ele, std::vector<Dof> &keys, int k=0) const  {
    if((*FilterEle)(ele))
      FilteredFS->getKeys(ele, keys);
    else
      BaseFS->getKeys(ele, keys);
  }
  
  virtual int getIncidentSpaceTag(int k=0) const {return BaseFS->getIncidentSpaceTag();}

  
  virtual void get(MElement *ele, int npts, IntPt *GP, std::vector<ContainerValType> &vvals) const  {
    if((*FilterEle)(ele))
      FilteredFS->get(ele, npts, GP, vvals);
    else
      BaseFS->get(ele, npts, GP, vvals);
  }
  
  virtual void getgradf(MElement *ele, int npts, IntPt *GP, std::vector< ContainerGradType > &vgrads) const{
    if((*FilterEle)(ele))
      FilteredFS->getgradf(ele, npts, GP, vgrads);
    else
      BaseFS->getgradf(ele, npts, GP, vgrads);
  }
  
  virtual void getgradfuvw(MElement *ele, int npts, IntPt *GP, std::vector< ContainerGradType > &vgrads) const{
    if((*FilterEle)(ele))
      FilteredFS->getgradfuvw(ele, npts, GP, vgrads);
    else
      BaseFS->getgradfuvw(ele, npts, GP, vgrads);
  }
  
  virtual void gethessfuvw(MElement *ele, int npts, IntPt *GP, std::vector< ContainerHessType > &vhesss) const{
    if((*FilterEle)(ele))
      FilteredFS->gethessfuvw(ele, npts, GP, vhesss);
    else
      BaseFS->gethessfuvw(ele, npts, GP, vhesss);
  }

  virtual RestrictedFilteredFSpace<T>* clone () const {return new RestrictedFilteredFSpace<T>(*this);}
};

#endif // RESTRICTEDFILTEREDFSPACE_H
