#include <iostream>
#include <fstream>
#include <cstdlib>

#include "test_utils.hh"

#include "geners/MultiFileArchive.hh"
#include "geners/ColumnPacker.hh"

using namespace gs;
using namespace std;

#ifdef CPP11_STD_AVAILABLE

static const char* filename;
static const char* objname;

void usage_and_exit(const char* prog)
{
    cerr << "\nUsage:  " << parse_progname(prog) 
         << "  filename  object_name\n" << endl;
    exit(1);
}

void read_big_tuple()
{
    MultiFileArchive ar(filename, "r", "Huge pack test");
    if (!ar.isReadable())
    {
        std::cerr << "Failed to open archive \"" << ar.name()
                  << "\" for reading" << std::endl;
        return;
    }

    double d;
    long double ld;
    long li;
    unsigned long uli;
    long long lli;
    unsigned long long ulli;
    auto t = std::tie(d, ld, li, uli, lli, ulli);
    
    typedef ColumnPacker<decltype(t)> Packer;
    CPReference<Packer> ref(ar, objname, "my category");
    assert(ref.unique());

    std::unique_ptr<Packer> nt = ref.get(0);

    const unsigned long nrows = nt->nRows();
    for (unsigned long i=0; i<nrows; ++i)
    {
        nt->rowContents(i, &t);
        unsigned long j = std::tuple_size<decltype(t)>::value*nrows;

        if (d != j++) cout << "Problem with d, row " << i << endl;
        if (ld != j++) cout << "Problem with ld, row " << i << endl;
        if ((unsigned long)li != j++) cout << "Problem with li, row " << i << endl;
        if (uli != j++) cout << "Problem with uli, row " << i << endl;
        if ((unsigned long long)lli != j++) cout << "Problem with lli, row " << i << endl;
        if (ulli != j++) cout << "Problem with ulli, row " << i << endl;
    }
    cout << "Read " << nrows << " rows" << endl;
}

int main(int argc, char const* argv[])
{
    if (argc != 3)
        usage_and_exit(argv[0]);

    filename = argv[1];
    objname = argv[2];

    const double t = time_of_run(read_big_tuple, 1);
    std::cout << "Program took " << t/1000000 << " sec" << std::endl;

    return 0;
}

#else // CPP11_STD_AVAILABLE

int main(int argc, char const* argv[])
{
    cout << "Please recompile with C++11 features enabled" << endl;
    return 0;
}

#endif // CPP11_STD_AVAILABLE
