#include <boost/mpi.hpp>
#include <boost/mpi/environment.hpp>

 //#include <plinkio.h>
#include <avail_mem.h>
#include <demo_chi2.h>

namespace mpi = boost::mpi;
namespace mt  = mpi::threading;

int main(int argc, char *argv[]) {
	mt::level mt_level = mt::multiple;
    boost::mpi::environment env(argc, argv, mt_level);
    mt ::level provided = env.thread_level();
    
    mpi::communicator world;
    if (world.rank() == 0){
        std::cout << "Asked the MPI environment to be created with threading level: "\
         << mt_level << std::endl;
        std::cout << "MPI Environment was created with threading level: " << provided \
         << std::endl;
    }

    char hammer_host[256];
    gethostname(hammer_host, 256);

    std::cout << "\nHello from process " << world.rank() << " of " << world.size()
        << " running on " << hammer_host << std::endl;

    int sample_size = 0;
    std::string data_file;
    std::string pval_file;
    std::string runtime_res;
    std::string data_path;
    int num_vars = 0;

    int opt;

    while ((opt = getopt(argc, argv, "d:f:s:p:r:v:")) != -1) {
    	switch(opt) {
    	case 'd':
    		data_file = optarg;
    		break;
    	case 'f':
    		data_path = optarg;
    		break;
    	case 's':
    		sample_size = atoi(optarg);
    		break;
    	case 'p':
    		pval_file = optarg;
    	case 'r':
    		runtime_res = optarg;
    	case 'v':
    		num_vars = atoi(optarg);
    		break;
    	}
    }

  	std::vector<string> headersS;
  	std::vector<double> yData;
	std::vector<std::vector<double>> sData;
    std::string full_path = "../" + data_file;

    size_t N = 1;
    size_t M = 1;
    size_t from = 0;

    ReadSNPFile(headersS,sData,yData,full_path, N, M, from);


    auto tot_sys_mem = getTotalSystemMemory();
    auto mem_test = ((yData.size() * (sizeof(double_t)) + (sData.size() * (sData.back().size() * sizeof(double_t)))))/tot_sys_mem;
    //Leave 20% buffer
    int batch_size = 0.8/mem_test;

    int rem = sample_size % world.size();
    int node_samples = sample_size/world.size();
    int node_start = world.rank()*node_samples + rem;
    //int node_stop = node_start+(node_samples-1);

    if (world.rank() < rem){
    	node_start = world.rank() * (node_samples+1);
    	//int node_stop = node_start + node_samples;
    }
    

    for (int i = 0; i < ceil(node_samples/batch_size); i++)
    {
    	int curr_batch = node_samples - (batch_size*i);
    	int batch_gen = batch_size;
    	if (curr_batch > batch_size){
    		batch_gen = curr_batch;
    	}

    	int file_start = node_start + (batch_size*i);

   		RunChi2(data_path, data_file, pval_file, runtime_res, std::to_string(batch_gen), std::to_string(num_vars), file_start);


    }
}



