/** @file phase_transition.cpp
 *
 *  @author Cory Alexander Balaton (coryab)
 *  @author Janita Ovidie Sandtrøen Willumsen (janitaws)
 *
 *  @version 1.0
 *
 *  @brief Sweep over different temperatures and generate data.
 *
 *  @details This program takes in 4 arguments: the start temperature,
 *  the end temperature, the amount of temperature points to simulate, and
 *  the amount of monte carlo samples to collect, in that order.
 *
 *  @bug No known bugs
 * */
#include "data_type.hpp"
#include "monte_carlo.hpp"
#include "utils.hpp"

#include <getopt.h>
#include <omp.h>
#include <string>

void usage(std::string filename)
{
    std::cout << "Usage: " << filename
              << " <start temperature> <end temperature> <points> "
                 "<lattice size> <cycles> <burn-in-time> <output file>\n\n"
              << "\t[ -h | --help ]\n";
    exit(-1);
}

/** @brief The main function
 *
 *  */
int main(int argc, char **argv)
{
    // Command options
    struct option long_options[] = {{"help", 0, 0, 0}, {NULL, 0, NULL, 0}};

    int option_index = -1;
    int c;

    while (true) {
        c = getopt_long(argc, argv, "h", long_options, &option_index);

        if (c == -1)
            break;

        switch (c) {
        case 0:
            switch (option_index) {
            case 0: // Not a mistake. This just goes to the default.
            default:
                usage(argv[0]);
            }
            break;
        case 'h':
        default:
            usage(argv[0]);
        }
    }
    // Check that the number of arguments is at least 8.
    if (argc < 8) {
        usage(argv[0]);
    }

    // Timing variables
    double t0, t1;
    t0 = omp_get_wtime();

    // Define/initialize variables
    double start = atof(argv[1]), end = atof(argv[2]);
    int points = atoi(argv[3]), cycles = atoi(argv[5]), L = atoi(argv[4]),
        burn_in_time = atoi(argv[6]), N = L * L;
    std::string outfile = argv[7];

    montecarlo::phase_transition(L, start, end, points, cycles,
                                 montecarlo::mcmc_parallel, outfile, burn_in_time);

    t1 = omp_get_wtime();

    std::cout << "Time: " << t1 - t0 << " seconds\n";
}
