#ifndef dplyr_Result_Mutater_H
#define dplyr_Result_Mutater_H

namespace dplyr {
    
    template <int RTYPE, typename Derived>
    class Mutater : public Result {
    public:
        
        virtual SEXP process(const GroupedDataFrame& gdf ){
            int ng = gdf.ngroups() ; 
            
            Vector<RTYPE> out = no_init(gdf.nrows()) ;
            GroupedDataFrame::group_iterator git = gdf.group_begin(); 
            for( int i=0; i<ng; i++, ++git){
                static_cast<Derived&>(*this).process_slice(out, *git, *git) ;
            }
            return out ;
        }
        
        virtual SEXP process(const RowwiseDataFrame& gdf ){
            int ng = gdf.ngroups() ; 
            
            Vector<RTYPE> out = no_init(gdf.nrows()) ;
            RowwiseDataFrame::group_iterator git = gdf.group_begin(); 
            for( int i=0; i<ng; i++, ++git){
                static_cast<Derived&>(*this).process_slice(out, *git, *git) ;
            }
            return out ;
        }
        
        virtual SEXP process(const FullDataFrame& df){
            Vector<RTYPE> out = no_init(df.nrows()) ;
            SlicingIndex index = df.get_index() ;
            static_cast<Derived&>(*this).process_slice( out, index, index );
            return out ;
        }
        
        virtual SEXP process(const SlicingIndex& index){
            int nrows = index.size() ;
            Vector<RTYPE> out = no_init(nrows) ;
            SlicingIndex fake(0, nrows) ;
            static_cast<Derived&>(*this).process_slice( out, index, fake );
            return out ;
        }
        
    } ;
    
}

#endif
