// Lemur OLAP library (c) 2003 National Research Council of Canada by Daniel Lemire, and Owen Kaser
 /**
 *  This program is free software; you can
 *  redistribute it and/or modify it under the terms of the GNU General Public
 *  License as published by the Free Software Foundation (version 2). This
 *  program is distributed in the hope that it will be useful, but WITHOUT ANY
 *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 *  FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 *  details. You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software Foundation,
 *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
#ifndef PERLC_INT_H
#define PERLC_INT_H

#include <bitset>
#include "normalizations.h"

// hard-coded paths in your C/C++ source code? ;-)

#ifndef PERLPGM_HOME
#define PERLPGM_HOME "/home/owen/cube-compress/asa_compress"
#endif

#ifndef DATADIR
#define DATADIR "/home/owen/OLAPData/OwenData"
#endif


/* This algorithm first runs the Perl/C 1-chunk normalizer, then
 * steals its output as its own.  I could get this sequencing by
 * composing the "read external" algorithm with a "invoke Perl",
 * but this seems bad form, besides weird...the "invoke Perl" algorithm
 * would not return any sensible normalization by itself.
 */

template <class _DT, class _LDT>
class PerlInvoker : public Normalization<_DT,_LDT> {
public:

PerlInvoker(string dataset, int algNo, int ordNo, int nChunks, vector<int>grpby):dsetName()
    {
        // parse off the "census", "weather" etc part from the binary file name
        // someday, learn to use POSIX <regex.h> from C++
        bool pastDot = false;
        for (string::reverse_iterator i=dataset.rbegin(); i != dataset.rend(); ++i) {
            if (*i == '/') break;
            if (pastDot) dsetName.insert(0,1,*i);
            if (*i == '.') pastDot = true;
        }
        cout << "dataset base name is " << dsetName;
        bitset<32> b;
        for (uint i=0; i < grpby.size(); ++i) b.set(grpby[i]);
        ostringstream cmdL;
        cmdL << algNo << " " << ordNo << " " << "/tmp/cubecode 1 " << nChunks;
        commandLineArgs = cmdL.str();

        ofstream os("/tmp/cubecode");
        os << b.to_ulong() << endl;
    }

virtual PerlInvoker* clone() const { return new PerlInvoker(*this);}
    virtual ~PerlInvoker() {}
    virtual const string getTextName(void) const {
        return "Invoke Perl normalizer with args " + commandLineArgs;
    }


    virtual norm_type computeNormalFrom( DataCube<_DT,_LDT>& DC,
            const norm_type initial);
private:
    string commandLineArgs;
    string dsetName;
};


template <class _DT, class _LDT>
norm_type PerlInvoker<_DT,_LDT>::
computeNormalFrom( DataCube<_DT,_LDT>& DC, const norm_type initial) {
    // yuck!  I think the Perl pgm expects to run in its own dir
    ostringstream commandsS;
    commandsS << "ln -sf " << DATADIR << "/config." << dsetName << ".txt" <<
    " " << PERLPGM_HOME << "/config.txt;";
    commandsS << "cd " << PERLPGM_HOME << " ; ./compress.pl " << commandLineArgs << endl;
    cout << "I will try to run " << commandsS.str() << " through the shell " << endl;
    int retcode = system(commandsS.str().c_str());
    cout << "tried, return code was " << retcode << endl;

    NormalizationReader<_DT,_LDT> reader(PERLPGM_HOME "/GCNorm.dat");
    return reader.computeNormalFrom(DC,initial);
}

#endif
