#include <iomanip>
#include <iostream>
#include <tuple>

#include "DBManager.h"


// helper function to print a tuple of any size
template<class Tuple, std::size_t N>
struct TuplePrinter {
    static void print(const Tuple& t) 
    {
        TuplePrinter<Tuple, N-1>::print(t);
        std::cout << ", " << std::get<N-1>(t);
    }
};
 
template<class Tuple>
struct TuplePrinter<Tuple, 1> {
    static void print(const Tuple& t) 
    {
        std::cout << std::get<0>(t);
    }
};
 
template<class... Args>
void print(const std::tuple<Args...>& t) 
{
    std::cout << "(";
    TuplePrinter<decltype(t), sizeof...(Args)>::print(t);
    std::cout << ")\n";
}


int main(int argc, char** argv)
{
    std::cout << "SQLite Proof of Concept Exerciser" << std::endl;

    // Make a DBManager instance which will connect to our test DB automagically
    DBManager db_mgr("database.db");
    
    // Make a query
    std::string query("SELECT Number, Words, Float FROM sample;");
    
    // Execute the query making sure the template params match up with the
    // query params
    int rc = 0;    
    auto results = db_mgr.execute_query<int64_t, std::string, double>(query, rc);
    std::cout << "Return code: " << rc << std::endl;
    
    // If we returned successfully, print out the result rows
    if (! rc)
    {
        uint32_t row_index = 0;
        for (auto row : *results)
        {
            std::cout << "Row: " << std::setw(4) << row_index << " - ";
            print(*row);
            ++row_index;
        }
    }
    
    return 0;
}
