/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2023,  Regents of the University of California,
 *                           Arizona Board of Regents,
 *                           Colorado State University,
 *                           University Pierre & Marie Curie, Sorbonne University,
 *                           Washington University in St. Louis,
 *                           Beijing Institute of Technology,
 *                           The University of Memphis.
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon).
 * See AUTHORS.md for complete list of NFD authors and contributors.
 *
 * NFD 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 3 of the License, or (at your option) any later version.
 *
 * NFD 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
 * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "command-parser.hpp"
#include "help.hpp"

#include "core/version.hpp"

#include <boost/tokenizer.hpp>
#include <fstream>
#include <iostream>

namespace nfd::tools::nfdc {

static int
main(int argc, char** argv)
{
  std::vector<std::string> args(argv + 1, argv + argc);

  CommandParser parser;
  registerCommands(parser);

  if (args.empty()) {
    helpList(std::cout, parser);
    return 0;
  }

  if (args[0] == "-V" || args[0] == "--version") {
    std::cout << NFD_VERSION_BUILD_STRING << std::endl;
    return 0;
  }

  struct Command
  {
    std::string noun, verb;
    CommandArguments ca;
    ExecuteCommand execute;
  };

  auto processLine = [&parser] (const std::vector<std::string>& line) -> Command {
    try {
      auto [noun, verb, ca, execute] = parser.parse(line, ParseMode::ONE_SHOT);
      return {noun, verb, ca, execute};
    }
    catch (const std::invalid_argument& e) {
      int ret = help(std::cout, parser, line);
      if (ret == 2)
        std::cerr << e.what() << std::endl;
      return {};
    }
  };

  std::list<Command> commands;

  if (args[0] == "-f" || args[0] == "--batch") {
    if (args.size() != 2) {
      std::cerr << "ERROR: Invalid command line arguments: " << args[0] << " should follow with batch-file."
                << " Use -h for more detail." << std::endl;
      return 2;
    }

    auto processIstream = [&commands, &processLine] (std::istream& is, const std::string& inputFile) {
      std::string line;
      size_t lineCounter = 0;
      while (std::getline(is, line)) {
        ++lineCounter;

        auto hasEscapeSlash = [] (const std::string& str) {
          auto count = std::count(str.rbegin(), str.rend(), '\\');
          return (count % 2) == 1;
        };
        while (!line.empty() && hasEscapeSlash(line)) {
          std::string extraLine;
          const auto& hasMore = std::getline(is, extraLine);
          ++lineCounter;
          line = line.substr(0, line.size() - 1) + extraLine;
          if (!hasMore) {
            break;
          }
        }
        boost::tokenizer<boost::escaped_list_separator<char>> tokenizer(
          line,
          boost::escaped_list_separator<char>("\\", " \t", "\"'"));

        auto firstNonEmptyToken = tokenizer.begin();
        while (firstNonEmptyToken != tokenizer.end() && firstNonEmptyToken->empty()) {
          ++firstNonEmptyToken;
        }

        // Ignore empty lines (or lines with just spaces) and lines that start with #
        // Non empty lines with trailing comment are not allowed and may trigger syntax error
        if (firstNonEmptyToken == tokenizer.end() || (*firstNonEmptyToken)[0] == '#') {
          continue;
        }

        std::vector<std::string> lineArgs;
        std::copy_if(firstNonEmptyToken, tokenizer.end(), std::back_inserter(lineArgs),
                     [] (const auto& t) { return !t.empty(); });

        auto cmd = processLine(lineArgs);
        if (cmd.noun.empty()) {
          std::cerr << "  >> Syntax error on line " << lineCounter << " of the batch in "
                    << inputFile << std::endl;
          return 2; // not exactly correct, but should be indication of an error, which already shown
        }
        commands.push_back(std::move(cmd));
      }
      return 0;
    };

    if (args[1] == "-") {
      auto retval = processIstream(std::cin, "standard input");
      if (retval != 0) {
        return retval;
      }
    }
    else {
      std::ifstream iff(args[1]);
      if (!iff) {
        std::cerr << "ERROR: Could not open `" << args[1] << "` batch file "
                  << "(" << strerror(errno) << ")" << std::endl;
        return 2;
      }
      auto retval = processIstream(iff, args[1]);
      if (retval != 0) {
        return retval;
      }
    }
  }
  else {
    commands.push_back(processLine(args));
  }

  try {
    ndn::Face face;
    ndn::KeyChain keyChain;
    ndn::nfd::Controller controller(face, keyChain);
    size_t commandCounter = 0;
    for (auto& command : commands) {
      ++commandCounter;
      ExecuteContext ctx{command.noun, command.verb, command.ca, 0,
                         std::cout, std::cerr, face, keyChain, controller};
      command.execute(ctx);

      if (ctx.exitCode != 0) {
        if (commands.size() > 1) {
          std::cerr << "  >> Failed to execute command on line " << commandCounter
                    << " of the batch file " << args[1] << std::endl;
          std::cerr << "  Note that nfdc has executed all commands on previous lines and "
                    << "stopped processing at this line" << std::endl;
        }

        return ctx.exitCode;
      }
    }
    return 0;
  }
  catch (const std::exception& e) {
    std::cerr << e.what() << std::endl;
    return 1;
  }
}

} // namespace nfd::tools::nfdc

int
main(int argc, char** argv)
{
  return nfd::tools::nfdc::main(argc, argv);
}
