#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <mpi.h>

#include "grid.h"
#include "cycletimer.h"
    
void usage(char *name) {
    printf("Usage: %s [-h] [-v] [-n GRID] [-b BMODE] [-e EPS] [-s STEPS]\n", name);
    printf("  -h       Print this message\n");
    printf("  -v       Verbose mode\n");
    printf("  -n GRID  Set grid size\n");
    printf("  -b BMODE Boundary conditions (h:horizontal, c:corner, d:diagonal, r:random)\n");
    printf("  -e EPS   Set convergence limit\n");
    printf("  -s STEPS Set step limit\n");
}



int main(int argc, char *argv[]) {
    int nrow = 40;
    int maxSteps = 1000;
    double epsilon = 0.0001;
    char mode = 'h';
    bool verbose = false;
    int c;
    int process_count = 1;
    int process_id = 0;
    int steps = 0;

    MPI_Init(NULL, NULL);
    MPI_Comm_size(MPI_COMM_WORLD, &process_count);
    MPI_Comm_rank(MPI_COMM_WORLD, &process_id);

    bool mpi_master = process_id == 0;
    char *optstring = "hvn:b:e:s:";
    bool run = true;

    while ((c = getopt(argc, argv, optstring)) != -1) {
	switch (c) {
	case 'h':
	    run = false;
	    if (mpi_master)
		usage(argv[0]);
	    MPI_Finalize();
	    exit(0);
	    break;
	case 'v':
	    verbose = true;
	case 'n':
	    nrow = atoi(optarg);
	    break;
	case 'b':
	    mode = optarg[0];
	    break;
	case 'e':
	    epsilon = atof(optarg);
	    break;
	case 's':
	    maxSteps = atoi(optarg);
	    break;
	default:
	    run = false;
	    if (mpi_master) {
		printf("Unknown command line option '%d'\n", c);
		usage(argv[0]);
	    }
	    MPI_Finalize();
	    exit(1);
	}
    }
    double start_time = currentSeconds();

    if (run)
	steps = solve(nrow, nrow, mode, epsilon, maxSteps, verbose, process_id, process_count);

    MPI_Finalize();

    if (mpi_master) {
	double seconds = currentSeconds() - start_time;
	long comps = (long) nrow * nrow * steps;
	double npc = seconds * 1e9 / comps;
	printf("%d rows.  %d processes.  %.2f seconds.  %ld grid point computations.  nanoseconds/comp. = %.2f\n",
	       nrow, process_count, seconds, comps, npc);
    }

    exit(0);
}
