/*
Serval DNA command-line parsing
Copyright (C) 2014-2015 Serval Project Inc.
Copyright (C) 2016 Flinders University

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include "commandline.h"
#include "conf.h"
#include "str.h"
#include "cli_stdio.h"

DEFINE_CMD(app_usage, CLIFLAG_PERMISSIVE_CONFIG,
  "Display command usage.",
  "help|-h|--help","...");
static int app_usage(const struct cli_parsed *parsed, struct cli_context *UNUSED(context))
{
  return cli_usage_parsed(parsed, XPRINTF_STDIO(stdout));
}

/* Parse the command line and load the configuration.  If a command was found then execute the
 * parsed command and return its return value.
 *
 * 'context' controls the command output.
 *
 * 'argv0' must be NULL or be a nul-terminated string containing the name or path of the executable.
 * It is used to emit diagnostic messages.
 *
 * 'argc' and 'args' must contain the command-line words to parse.
 */
int commandline_main(struct cli_context *context, const char *argv0, int argc, const char *const *args)
{
  fd_clearstats();
  IN();

  cf_init();

  struct cli_parsed parsed;
  int result = cli_parse(argc, args, SECTION_START(commands), SECTION_END(commands), &parsed);
  switch (result) {
  case 0:
    // Do not run the command if the configuration does not load ok.
    if (((parsed.commands[parsed.cmdi].flags & CLIFLAG_PERMISSIVE_CONFIG) ? cf_reload_permissive() : cf_reload()) != -1)
      result = cli_invoke(&parsed, context);
    else {
      strbuf b = strbuf_alloca(160);
      strbuf_append_argv(b, argc, args);
      result = WHYF("configuration defective, not running command: %s", strbuf_str(b));
    }
    break;
  case 1:
  case 2:
    // Load configuration so that log messages can get out.
    cf_reload_permissive();
    NOWHENCE(HINTF("Run \"%s help\" for more information.", argv0 ? argv0 : "servald"));
    result =-1;
    break;
  default:
    // Load configuration so that log error messages can get out.
    cf_reload_permissive();
    break;
  }

  CALL_TRIGGER(cmd_cleanup, context);

  OUT();

  if (IF_DEBUG(timing))
    fd_showstats();
  return result;
}

// Put a dummy no-op trigger callback into the "cmd_cleanup" trigger section,
// otherwise if no other object provides one, the link will fail with errors like:
// undefined reference to `__start_tr_cmd_cleanup'
// undefined reference to `__stop_tr_cmd_cleanup'

static void __dummy_on_cmd_cleanup() {}
DEFINE_TRIGGER(cmd_cleanup, __dummy_on_cmd_cleanup);