
#include <stdlib.h>
#include <argp.h>

#include "config.h"
#include "universe.h"

struct options {
  int outputLevel;
  int port;
  char* directory;
};

static char commandLineDocumentation[] =
  "Void -- a moderately multiplayer persistent online real-time strategy game\v"
  "By default, runs with the data in the ./universe/ directory. If it doesn't "
  "exist, the directory is created, and populated with default configuration files.";

static char commandLineUsage[] = "[DIRECTORY]";

static struct argp_option commandLineOptions[] = {
  {"verbose",  'v', 0,      0,            "Produce verbose output" },
  {"quiet",    'q', 0,      0,            "Don't produce any output" },
  // {"silent",   's', 0,      OPTION_ALIAS },
  {"port",     'p', "PORT", 0,            "Listen for connections on PORT" },
  { 0 }
};

static error_t commandLineParser(int key, char* arg, struct argp_state* state) {
  /* Get the input argument from argp_parse, which we know is a
     pointer to our arguments structure. */
  struct options* arguments = static_cast<struct options*> (state->input);

  switch (key) {
  case 'q':
  case 's':
    arguments->outputLevel = 0;
    break;
  case 'v':
    arguments->outputLevel = 2;
    break;
  case 'p': {
    int p = atoi(arg);
    if (p <= 0 || p >= 65535)
      argp_usage(state); /* out of range */
    arguments->port = p;
    break;
  }
  case ARGP_KEY_ARG:
    if (state->arg_num >= 1)
      argp_usage(state); /* can only set one directory */
    arguments->directory = arg;
    break;
  default:
    return ARGP_ERR_UNKNOWN;
  }
  return 0;
}

static struct argp argp = { commandLineOptions,
                            commandLineParser,
                            commandLineUsage,
                            commandLineDocumentation };

int main(int argc, char* argv []) {

  // parse arguments
  struct options options;
  options.outputLevel = 1;
  options.port = PORT;
  options.directory = "./universe/";
  argp_parse(&argp, argc, argv, 0, 0, &options);

  // big bang
  Universe* universe = new Universe(options.outputLevel, options.port, options.directory);
  universe->run();
  delete universe;

  // exit
  return 0;
}
