/*
 * Main
 */
int main(int argc, char *argv[]) {
  ola::AppInit(&argc,
               argv,
               "[options] <config_file>",
               "Run programs based on the values in a DMX stream.");

  if (FLAGS_offset >= ola::DMX_UNIVERSE_SIZE) {
    std::cerr << "Invalid slot offset: " << FLAGS_offset << std::endl;
    exit(ola::EXIT_USAGE);
  }

  if (argc != 2)
    ola::DisplayUsageAndExit();

  // setup the default context
  global_context = new Context();
  OLA_INFO << "Loading config from " << argv[1];

  // open the config file
  if (freopen(argv[1], "r", stdin) == NULL) {
    OLA_FATAL << "File " << argv[1] << " cannot be opened.\n";
    exit(ola::EXIT_DATAERR);
  }

  yyparse();

  if (FLAGS_validate) {
    std::cout << "File " << argv[1] << " is valid." << std::endl;
    // TODO(Peter): Print some stats here, validate the offset if supplied
    STLDeleteValues(&global_slots);
    exit(ola::EXIT_OK);
  }

  // if we got to this stage the config is ok and we want to run it, setup the
  // client
  ola::OlaCallbackClientWrapper wrapper;

  if (!wrapper.Setup())
    exit(ola::EXIT_UNAVAILABLE);

  ss = wrapper.GetSelectServer();

  if (!InstallSignals())
    exit(ola::EXIT_OSERR);

  // create the vector of Slot
  SlotList slots;
  if (ApplyOffset(FLAGS_offset, &slots)) {
    // setup the trigger
    DMXTrigger trigger(global_context, slots);

    // register for DMX
    ola::OlaCallbackClient *client = wrapper.GetClient();
    client->SetDmxCallback(
        ola::NewCallback(&NewDmx,
                         static_cast<unsigned int>(FLAGS_universe),
                         &trigger));
    client->RegisterUniverse(FLAGS_universe, ola::REGISTER, NULL);

    // start the client
    wrapper.GetSelectServer()->Run();
  }

  // cleanup
  STLDeleteElements(&slots);
}