/*
 Copyright (c) 1996-2020 Freeciv21 and Freeciv contributors. This file is
 __    __          part of Freeciv21. Freeciv21 is free software: you can
/ \\..// \    redistribute it and/or modify it under the terms of the GNU
  ( oo )        General Public License  as published by the Free Software
   \__/         Foundation, either version 3 of the License,  or (at your
                      option) any later version. You should have received
    a copy of the GNU General Public License along with Freeciv21. If not,
                  see https://www.gnu.org/licenses/.
 */

#include <fc_config.h>

#include <QFile>
#include <cstdlib>
#include <cstring>

// Qt
#include <QCommandLineParser>
#include <QCoreApplication>

// utility
#include "astring.h"
#include "fciconv.h"
#include "fcintl.h"
#include "log.h"
#include "registry.h"
#include "support.h"

// common
#include "capstr.h"
#include "connection.h"
#include "events.h"
#include "fc_interface.h"
#include "fc_types.h" // LINE_BREAK
#include "game.h"
#include "government.h"
#include "helpdata.h"
#include "improvement.h"
#include "map.h"
#include "movement.h"
#include "player.h"
#include "version.h"

// server
#include "commands.h"
#include "console.h"
#include "ruleset.h"
#include "sernet.h"
#include "settings.h"
#include "srv_main.h"

/* tools/shared */
#include "tools_fc_interface.h"

enum manuals {
  MANUAL_SETTINGS,
  MANUAL_COMMANDS,
  MANUAL_TERRAIN,
  MANUAL_BUILDINGS,
  MANUAL_WONDERS,
  MANUAL_GOVS,
  MANUAL_UNITS,
  MANUAL_TECHS,
  MANUAL_COUNT
};

struct tag_types {
  const char *file_ext;
  const char *header;
  const char *title_begin;
  const char *title_end;
  const char *sect_title_begin;
  const char *sect_title_end;
  const char *item_begin;
  const char *item_end;
  const char *subitem_begin;
  const char *subitem_end;
  const char *tail;
};

struct tag_types html_tags = {
    // file extension
    "html",

    // header
    "<html><head><link rel=\"stylesheet\" type=\"text/css\" "
    "href=\"manual.css\"/><meta http-equiv=\"Content-Type\" "
    "content=\"text/html; charset=UTF-8\"/></head><body>\n\n",

    // title begin
    "<h1>",

    // title end
    "</h1>",

    // section title begin
    "<h3 class='section'>",

    // section title end
    "</h3>",

    // item begin
    "<div class='item' id='%s%d'>\n",

    // item end
    "</div>\n",

    // subitem begin
    "<pre class='%s'>",

    // subitem end
    "</pre>\n",

    // tail
    "</body></html>"};

struct tag_types wiki_tags = {
    // file extension
    "mediawiki",

    // header
    " ",

    // title begin
    "=",

    // title end
    "=",

    // section title begin
    "===",

    // section title end
    "===",

    // item begin
    "----\n<!-- %s %d -->\n",

    // item end
    "\n",

    // subitem begin
    "<!-- %s -->\n",

    // subitem end
    "\n",

    // tail
    " "};

static QString ruleset;

/**
   Write a server manual, then quit.
 */
static bool manual_command(struct tag_types *tag_info)
{
  FILE *doc = nullptr;
  char filename[40];
  struct connection my_conn;

  // Default client access.
  connection_common_init(&my_conn);
  my_conn.access_level = ALLOW_CTRL;

  // Reset aifill to zero
  game.info.aifill = 0;

  if (!load_rulesets(nullptr, nullptr, false, nullptr, false, false,
                     false)) {
    // Failed to load correct ruleset
    connection_common_close(&my_conn);
    return false;
  }

  for (int imanuals = 0; imanuals < MANUAL_COUNT; imanuals++) {
    enum manuals manuals = static_cast<enum manuals>(imanuals);
    int i;
    int ri;

    fc_snprintf(filename, sizeof(filename), "%s%d.%s",
                game.server.rulesetdir, manuals + 1, tag_info->file_ext);

    if (QFile::exists(filename) || !(doc = fc_fopen(filename, "w"))) {
      qCritical(_("Could not write manual file %s."), filename);
      connection_common_close(&my_conn);
      return false;
    }

    fprintf(doc, "%s", tag_info->header);
    fprintf(doc, "<!-- Generated by freeciv21-manual version %s -->\n\n",
            freeciv21_version());

    switch (manuals) {
    case MANUAL_SETTINGS:
      // TRANS: markup ... Freeciv21 version ... ruleset name ... markup
      fprintf(doc, _("%sFreeciv21 %s server options (%s)%s\n\n"),
              tag_info->title_begin, freeciv21_version(), game.control.name,
              tag_info->title_end);
      settings_iterate(SSET_ALL, pset)
      {
        char buf[256];
        const char *sethelp;

        fprintf(doc, tag_info->item_begin, "setting", setting_number(pset));
        fprintf(doc, "%s%s - %s%s\n\n", tag_info->sect_title_begin,
                setting_name(pset), _(setting_short_help(pset)),
                tag_info->sect_title_end);
        sethelp = _(setting_extra_help(pset, true));
        if (strlen(sethelp) > 0) {
          QString help = sethelp;
          help = break_lines(help, LINE_BREAK);
          help = help.toHtmlEscaped();
          fprintf(doc, "<pre>%s</pre>\n\n", qUtf8Printable(help));
        }
        fprintf(doc, "<p class=\"misc\">");
        fprintf(doc, _("Level: %s.<br>"),
                _(sset_level_name(setting_level(pset))));
        fprintf(doc, _("Category: %s.<br>"),
                _(sset_category_name(setting_category(pset))));

        /* first check if the setting is locked because this is included in
         * the function setting_is_changeable() */
        if (setting_locked(pset)) {
          fprintf(doc, _("Is locked by the ruleset."));
        } else if (!setting_is_changeable(pset, &my_conn, nullptr, 0)) {
          fprintf(doc, _("Can only be used in server console."));
        }

        fprintf(doc, "</p>\n");
        setting_default_name(pset, true, buf, sizeof(buf));
        switch (setting_type(pset)) {
        case SST_INT:
          fprintf(doc, "\n<p class=\"bounds\">%s %d, %s %s, %s %d</p>\n",
                  _("Minimum:"), setting_int_min(pset), _("Default:"), buf,
                  _("Maximum:"), setting_int_max(pset));
          break;
        case SST_ENUM: {
          const char *value;

          fprintf(doc, "\n<p class=\"bounds\">%s</p>",
                  _("Possible values:"));
          for (i = 0; (value = setting_enum_val(pset, i, false)); i++) {
            fprintf(doc, "\n<p class=\"bounds\"><li/> %s: \"%s\"</p>", value,
                    setting_enum_val(pset, i, true));
          }
        } break;
        case SST_BITWISE: {
          const char *value;

          fprintf(
              doc, "\n<p class=\"bounds\">%s</p>",
              _("Possible values (option can take any number of these):"));
          for (i = 0; (value = setting_bitwise_bit(pset, i, false)); i++) {
            fprintf(doc, "\n<p class=\"bounds\"><li/> %s: \"%s\"</p>", value,
                    setting_bitwise_bit(pset, i, true));
          }
        } break;
        case SST_BOOL:
        case SST_STRING:
          break;
        case SST_COUNT:
          fc_assert(setting_type(pset) != SST_COUNT);
          break;
        }
        if (SST_INT != setting_type(pset)) {
          fprintf(doc, "\n<p class=\"bounds\">%s %s</p>\n", _("Default:"),
                  buf);
        }
        if (setting_non_default(pset)) {
          fprintf(doc, _("\n<p class=\"changed\">Value set to %s</p>\n"),
                  setting_value_name(pset, true, buf, sizeof(buf)));
        }

        fprintf(doc, "%s", tag_info->item_end);
      }
      settings_iterate_end;
      break;

    case MANUAL_COMMANDS:
      // TRANS: markup ... Freeciv21 version ... markup
      fprintf(doc, _("%sFreeciv21 %s server commands%s\n\n"),
              tag_info->title_begin, freeciv21_version(),
              tag_info->title_end);
      for (i = 0; i < CMD_NUM; i++) {
        const struct command *cmd = command_by_number(i);

        fprintf(doc, tag_info->item_begin, "cmd", i);
        fprintf(doc, "%s%s  -  %s%s\n\n", tag_info->sect_title_begin,
                command_name(cmd), command_short_help(cmd),
                tag_info->sect_title_end);
        if (command_synopsis(cmd)) {
          QString cmdstr = command_synopsis(cmd);
          cmdstr = cmdstr.toHtmlEscaped();
          fprintf(doc, _("<table>\n<tr>\n<td valign=\"top\">"
                         "<pre>Synopsis:</pre></td>\n<td>"));
          fprintf(doc, "<pre>%s</pre></td></tr></table>",
                  qUtf8Printable(cmdstr));
        }
        fprintf(doc, _("<p class=\"level\">Level: %s</p>\n"),
                cmdlevel_name(command_level(cmd)));
        {
          QString help = command_extra_help(cmd);
          if (!help.isEmpty()) {
            help = break_lines(help, LINE_BREAK);
            help = help.toHtmlEscaped();
            fprintf(doc, "\n");
            fprintf(doc, _("<p>Description:</p>\n\n"));
            fprintf(doc, "<pre>%s</pre>\n", qUtf8Printable(help));
          }
        }

        fprintf(doc, "%s", tag_info->item_end);
      }
      break;

    case MANUAL_TERRAIN:
      // TRANS: markup ... Freeciv21 version ... ruleset name ... markup
      fprintf(doc, _("%sFreeciv21 %s terrain help (%s)%s\n\n"),
              tag_info->title_begin, freeciv21_version(), game.control.name,
              tag_info->title_end);
      fprintf(doc, "<table><tr bgcolor=#9bc3d1><th>%s</th>", _("Terrain"));
      fprintf(doc, "<th>F/P/T</th><th>%s</th>", _("Resources"));
      fprintf(doc, "<th>%s<br/>%s</th>", _("Move cost"), _("Defense bonus"));
      fprintf(doc, "<th>%s<br/>%s<br/>%s<br/>%s<br/>%s<br/>%s<br/>(%s)</th>",
              _("Irrigation"), _("Cultivate"), _("Mining"), _("Plant"),
              _("Transform"),
              // xgettext:no-c-format
              _("% of Road bonus"), _("turns"));
      fprintf(doc, "<th>%s<br/>%s</th>", _("Clean pollution"),
              _("Clean fallout"));
      ri = 0;
      if (game.control.num_road_types > 0) {
        fprintf(doc, "<th>");
      }
      extra_type_by_cause_iterate(EC_ROAD, pextra)
      {
        if (++ri < game.control.num_road_types) {
          fprintf(doc, "%s<br/>", extra_name_translation(pextra));
        } else {
          // Last one
          fprintf(doc, "%s</th>", extra_name_translation(pextra));
        }
      }
      extra_type_by_cause_iterate_end;
      fprintf(doc, "</tr>\n\n");
      terrain_type_iterate(pterrain)
      {
        struct extra_type **r;

        if (0 == qstrlen(terrain_rule_name(pterrain))) {
          // Must be a disabled piece of terrain
          continue;
        }

        fprintf(doc, "<tr><td>%s</td>", terrain_name_translation(pterrain));
        fprintf(doc, "<td>%d/%d/%d</td>\n", pterrain->output[O_FOOD],
                pterrain->output[O_SHIELD], pterrain->output[O_TRADE]);

        fprintf(doc, "<td><table width=\"100%%\">\n");
        for (r = pterrain->resources; *r; r++) {
          fprintf(doc,
                  "<tr><td>%s</td><td align=\"right\">%d/%d/%d</td></tr>\n",
                  extra_name_translation(*r),
                  (*r)->data.resource->output[O_FOOD],
                  (*r)->data.resource->output[O_SHIELD],
                  (*r)->data.resource->output[O_TRADE]);
        }
        fprintf(doc, "</table></td>\n");

        fprintf(doc, "<td align=\"center\">%d<br/>+%d%%</td>\n",
                pterrain->movement_cost, pterrain->defense_bonus);

        fprintf(doc, "<td><table width=\"100%%\">\n");
        if (pterrain->irrigation_time != 0) {
          fprintf(doc,
                  "<tr><td>+%d F</td><td align=\"right\">(%d)</td></tr>\n",
                  pterrain->irrigation_food_incr, pterrain->irrigation_time);
        } else {
          fprintf(doc, "<tr><td>%s</td></tr>\n", _("impossible"));
        }
        if (pterrain->irrigation_result != nullptr
            && pterrain->irrigation_result != pterrain) {
          fprintf(doc, "<tr><td>%s</td><td align=\"right\">(%d)</td></tr>\n",
                  terrain_name_translation(pterrain->irrigation_result),
                  pterrain->cultivate_time);
        } else {
          fprintf(doc, "<tr><td>%s</td></tr>\n", _("impossible"));
        }
        if (pterrain->mining_time != 0) {
          fprintf(doc,
                  "<tr><td>+%d P</td><td align=\"right\">(%d)</td></tr>\n",
                  pterrain->mining_shield_incr, pterrain->mining_time);
        } else {
          fprintf(doc, "<tr><td>%s</td></tr>\n", _("impossible"));
        }
        if (pterrain->mining_result != nullptr
            && pterrain->mining_result != pterrain) {
          fprintf(doc, "<tr><td>%s</td><td align=\"right\">(%d)</td></tr>\n",
                  terrain_name_translation(pterrain->mining_result),
                  pterrain->plant_time);
        } else {
          fprintf(doc, "<tr><td>%s</td></tr>\n", _("impossible"));
        }

        if (pterrain->transform_result) {
          fprintf(doc, "<tr><td>%s</td><td align=\"right\">(%d)</td></tr>\n",
                  terrain_name_translation(pterrain->transform_result),
                  pterrain->transform_time);
        } else {
          fprintf(doc, "<tr><td>-</td><td align=\"right\">(-)</td></tr>\n");
        }
        fprintf(doc, "<tr><td>%d / %d / %d</td></tr>\n</table></td>\n",
                pterrain->road_output_incr_pct[O_FOOD],
                pterrain->road_output_incr_pct[O_SHIELD],
                pterrain->road_output_incr_pct[O_TRADE]);

        fprintf(doc, "<td align=\"center\">%d / %d</td>",
                pterrain->clean_pollution_time,
                pterrain->clean_fallout_time);

        ri = 0;
        if (game.control.num_road_types > 0) {
          fprintf(doc, "<td>");
        }
        extra_type_by_cause_iterate(EC_ROAD, pextra)
        {
          if (++ri < game.control.num_road_types) {
            fprintf(doc, "%d / ",
                    terrain_extra_build_time(pterrain, ACTIVITY_GEN_ROAD,
                                             pextra));
          } else {
            fprintf(doc, "%d</td>",
                    terrain_extra_build_time(pterrain, ACTIVITY_GEN_ROAD,
                                             pextra));
          }
        }
        extra_type_by_cause_iterate_end;
        fprintf(doc, "</tr>\n\n");
      }
      terrain_type_iterate_end;

      fprintf(doc, "</table>\n");

      break;

    case MANUAL_BUILDINGS:
    case MANUAL_WONDERS:
      if (manuals == MANUAL_BUILDINGS) {
        // TRANS: markup ... Freeciv21 version ... ruleset name ... markup
        fprintf(doc, _("%sFreeciv21 %s buildings help (%s)%s\n\n"),
                tag_info->title_begin, freeciv21_version(),
                game.control.name, tag_info->title_end);
      } else {
        // TRANS: markup ... Freeciv21 version ... ruleset name ... markup
        fprintf(doc, _("%sFreeciv21 %s wonders help (%s)%s\n\n"),
                tag_info->title_begin, freeciv21_version(),
                game.control.name, tag_info->title_end);
      }

      fprintf(doc,
              "<table>\n<tr bgcolor=#9bc3d1><th>%s</th>"
              "<th>%s<br/>%s</th><th>%s<br/>%s</th><th>%s</th></tr>\n\n",
              _("Name"), _("Cost"), _("Upkeep"), _("Requirement"),
              _("Obsolete by"), _("More info"));

      improvement_iterate(pimprove)
      {
        char buf[64000];
        struct advance *obs_tech = nullptr;

        if (!valid_improvement(pimprove)
            || is_great_wonder(pimprove) == (manuals == MANUAL_BUILDINGS)) {
          continue;
        }

        helptext_building(buf, sizeof(buf), nullptr, nullptr, pimprove,
                          nullptr);

        fprintf(doc,
                "<tr><td>%s</td>\n"
                "<td align=\"center\"><b>%d</b><br/>%d</td>\n<td>",
                improvement_name_translation(pimprove), pimprove->build_cost,
                pimprove->upkeep);

        requirement_vector_iterate(&pimprove->reqs, req)
        {
          char text[512], text2[512];
          fc_snprintf(text2, sizeof(text2),
                      // TRANS: improvement requires a feature to be absent.
                      req->present ? "%s" : _("no %s"),
                      VUT_NONE != req->source.kind
                          ? universal_name_translation(&req->source, text,
                                                       sizeof(text))
                          : Q_("?req:None"));
          fprintf(doc, "%s<br/>", text2);
        }
        requirement_vector_iterate_end;

        requirement_vector_iterate(&pimprove->obsolete_by, pobs)
        {
          if (pobs->source.kind == VUT_ADVANCE) {
            obs_tech = pobs->source.value.advance;
            break;
          }
        }
        requirement_vector_iterate_end;

        fprintf(doc, "<em>%s</em></td>\n",
                obs_tech != nullptr ? advance_name_translation(obs_tech)
                                    : Q_("?tech:None"));
        fprintf(doc, "<td>%s</td>\n</tr>\n\n", buf);
      }
      improvement_iterate_end;
      fprintf(doc, "</table>");
      break;

    case MANUAL_GOVS:
      /* Freeciv-web uses (parts of) the government HTML output in its own
       * manual pages. */
      // FIXME: this doesn't resemble the wiki manual at all.
      // TRANS: markup ... Freeciv21 version ... ruleset name ... markup
      fprintf(doc, _("%sFreeciv21 %s governments help (%s)%s\n\n"),
              tag_info->title_begin, freeciv21_version(), game.control.name,
              tag_info->title_end);
      for (auto &pgov : governments) {
        char buf[64000];
        fprintf(doc, tag_info->item_begin, "gov", pgov.item_number);
        fprintf(doc, "%s%s%s\n\n", tag_info->sect_title_begin,
                government_name_translation(&pgov),
                tag_info->sect_title_end);
        fprintf(doc, tag_info->subitem_begin, "helptext");
        helptext_government(buf, sizeof(buf), nullptr, nullptr, &pgov);
        fprintf(doc, "%s\n\n", buf);
        fprintf(doc, "%s", tag_info->subitem_end);
        fprintf(doc, "%s", tag_info->item_end);
      };
      break;

    case MANUAL_UNITS:
      /* Freeciv-web uses (parts of) the unit type HTML output in its own
       * manual pages. */
      // FIXME: this doesn't resemble the wiki manual at all.
      // TRANS: markup ... Freeciv21 version ... ruleset name ... markup
      fprintf(doc, _("%sFreeciv21 %s unit types help (%s)%s\n\n"),
              tag_info->title_begin, freeciv21_version(), game.control.name,
              tag_info->title_end);
      unit_type_iterate(putype)
      {
        char buf[64000];

        fprintf(doc, tag_info->item_begin, "utype", putype->item_number);
        fprintf(doc, "%s%s%s\n\n", tag_info->sect_title_begin,
                utype_name_translation(putype), tag_info->sect_title_end);
        fprintf(doc, tag_info->subitem_begin, "cost");
        fprintf(doc,
                PL_("Cost: %d shield", "Cost: %d shields",
                    utype_build_shield_cost_base(putype)),
                utype_build_shield_cost_base(putype));
        fprintf(doc, "%s", tag_info->subitem_end);
        fprintf(doc, tag_info->subitem_begin, "upkeep");
        fprintf(doc, _("Upkeep: %s"), helptext_unit_upkeep_str(putype));
        fprintf(doc, "%s", tag_info->subitem_end);
        fprintf(doc, tag_info->subitem_begin, "moves");
        fprintf(doc, _("Moves: %s"),
                qUtf8Printable(move_points_text(putype->move_rate, true)));
        fprintf(doc, "%s", tag_info->subitem_end);
        fprintf(doc, tag_info->subitem_begin, "vision");
        fprintf(doc, _("Vision: %d"),
                (int) sqrt((double) putype->vision_radius_sq));
        fprintf(doc, "%s", tag_info->subitem_end);
        fprintf(doc, tag_info->subitem_begin, "attack");
        fprintf(doc, _("Attack: %d"), putype->attack_strength);
        fprintf(doc, "%s", tag_info->subitem_end);
        fprintf(doc, tag_info->subitem_begin, "defense");
        fprintf(doc, _("Defense: %d"), putype->defense_strength);
        fprintf(doc, "%s", tag_info->subitem_end);
        fprintf(doc, tag_info->subitem_begin, "firepower");
        fprintf(doc, _("Firepower: %d"), putype->firepower);
        fprintf(doc, "%s", tag_info->subitem_end);
        fprintf(doc, tag_info->subitem_begin, "hitpoints");
        fprintf(doc, _("Hitpoints: %d"), putype->hp);
        fprintf(doc, "%s", tag_info->subitem_end);
        fprintf(doc, tag_info->subitem_begin, "obsolete");
        fprintf(doc, _("Obsolete by: %s"),
                U_NOT_OBSOLETED == putype->obsoleted_by
                    ? Q_("?utype:None")
                    : utype_name_translation(putype->obsoleted_by));
        fprintf(doc, "%s", tag_info->subitem_end);
        fprintf(doc, tag_info->subitem_begin, "helptext");
        helptext_unit(buf, sizeof(buf), nullptr, "", putype, nullptr);
        fprintf(doc, "%s", buf);
        fprintf(doc, "%s", tag_info->subitem_end);
        fprintf(doc, "%s", tag_info->item_end);
      }
      unit_type_iterate_end;
      break;

    case MANUAL_TECHS:
      // FIXME: this doesn't resemble the wiki manual at all.
      // TRANS: markup ... Freeciv21 version ... ruleset name ... markup
      fprintf(doc, _("%sFreeciv21 %s tech help (%s)%s\n\n"),
              tag_info->title_begin, freeciv21_version(), game.control.name,
              tag_info->title_end);
      advance_iterate(A_FIRST, ptech)
      {
        if (valid_advance(ptech)) {
          char buf[64000];

          fprintf(doc, tag_info->item_begin, "tech", ptech->item_number);
          fprintf(doc, "%s%s%s\n\n", tag_info->sect_title_begin,
                  advance_name_translation(ptech), tag_info->sect_title_end);

          fprintf(doc, tag_info->subitem_begin, "helptext");
          helptext_advance(buf, sizeof(buf), nullptr, "", ptech->item_number,
                           nullptr);
          fprintf(doc, "%s", buf);
          fprintf(doc, "%s", tag_info->subitem_end);

          fprintf(doc, "%s", tag_info->item_end);
        }
      }
      advance_iterate_end;
      break;

    case MANUAL_COUNT:
      Q_UNREACHABLE();
      break;
    } // switch

    fprintf(doc, "%s", tag_info->tail);
    fclose(doc);
    qInfo(_("Manual file %s successfully written."), filename);
  } // manuals

  connection_common_close(&my_conn);
  return true;
}

/**
   Entry point of whole freeciv-manual program
 */
int main(int argc, char **argv)
{
  int retval = EXIT_SUCCESS;
  struct tag_types *tag_info = &html_tags;

  QCoreApplication app(argc, argv);
  QCoreApplication::setApplicationVersion(freeciv21_version());

  init_nls();
  init_character_encodings(FC_DEFAULT_DATA_ENCODING, false);

  QCommandLineParser parser;
  parser.addHelpOption();
  parser.addVersionOption();

  bool ok = parser.addOptions({
      {{"d", _("debug")},
       // TRANS: Do not translate "fatal", "critical", "warning", "info" or
       //        "debug". It's exactly what the user must type.
       _("Set debug log level (fatal/critical/warning/info/debug)."),
       _("LEVEL"),
       QStringLiteral("info")},
      {{"F", "Fatal"}, _("Raise a signal on failed assertion.")},
      {{"l", "log"},
       _("Use FILE as logfile."),
       // TRANS: Command-line argument
       _("FILE")},
      {{"r", "ruleset"},
       _("Make manual for RULESET."),
       // TRANS: Command-line argument
       _("RULESET")},
      {{"w", "wiki"}, _("Write manual in wiki format.")},
  });
  if (!ok) {
    qFatal("Adding command line arguments failed.");
  }

  // Parse
  parser.process(app);

  // Process the parsed options
  if (!log_init(parser.value(QStringLiteral("debug")))) {
    exit(EXIT_FAILURE);
  }
  fc_assert_set_fatal(parser.isSet(QStringLiteral("Fatal")));
  if (parser.isSet(QStringLiteral("ruleset"))) {
    if (parser.values(QStringLiteral("ruleset")).size() > 1) {
      fc_fprintf(stderr, _("Multiple rulesets requested. Only one ruleset "
                           "at time supported.\n"));
      exit(EXIT_FAILURE);
    } else {
      ruleset = parser.value(QStringLiteral("ruleset"));
    }
  }
  if (parser.isSet(QStringLiteral("log"))) {
    srvarg.log_filename = parser.value(QStringLiteral("log"));
  }
  if (parser.isSet(QStringLiteral("wiki"))) {
    tag_info = &wiki_tags;
  }

  init_our_capability();

  // must be before con_log_init()
  init_connections();
  con_log_init(srvarg.log_filename);
  // logging available after this point

  // Get common code to treat us as a tool.
  i_am_tool();

  /* Initialize the fc_interface functions needed to generate the help
   * text. */
  fc_interface_init_tool();

  // Initialize game with default values
  game_init(false);

  // Set ruleset user requested in to use
  if (!ruleset.isEmpty()) {
    sz_strlcpy(game.server.rulesetdir, qUtf8Printable(ruleset));
  }

  settings_init(false);

  if (!manual_command(tag_info)) {
    retval = EXIT_FAILURE;
  }

  con_log_close();
  free_libfreeciv();
  free_nls();

  return retval;
}
