/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2022, Regents of the University of California.
 *
 * This file is part of NDNS (Named Data Networking Domain Name Service).
 * See AUTHORS.md for complete list of NDNS authors and contributors.
 *
 * NDNS 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.
 *
 * NDNS 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
 * NDNS, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "logger.hpp"
#include "ndns-label.hpp"
#include "daemon/rrset-factory.hpp"
#include "mgmt/management-tool.hpp"
#include "util/util.hpp"

#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/program_options.hpp>

#include <iostream>

NDNS_LOG_INIT(AddRrTool);

int
main(int argc, char* argv[])
{
  using std::string;
  using namespace ndn;

  int ttlInt = -1;
  int versionInt = -1;
  string zoneStr;
  Name dsk;
  string db = ndns::getDefaultDatabaseFile();
  string rrLabelStr;
  string rrTypeStr;
  std::vector<std::string> content;
  string file = "-";
  string encoding = "base64";
  bool setFile = false;
  bool needResign = true;
  try {
    namespace po = boost::program_options;
    po::variables_map vm;

    po::options_description options("Generic Options");
    options.add_options()
      ("help,h",  "print this help message and exit")
      ("db,b",    po::value<std::string>(&db)->default_value(db), "path to NDNS database file")
      ;

    po::options_description config("Record Options");
    config.add_options()
      ("dsk,d", po::value<Name>(&dsk), "Set the name of DSK's certificate. "
       "Default: use default DSK and its default certificate")
      ("content,c", po::value<std::vector<std::string>>(&content),
       "Set the content of resource record. Default: empty string")
      ("ttl,a", po::value<int>(&ttlInt), "Set ttl of the rrset. Default: 3600 seconds")
      ("version,v", po::value<int>(&ttlInt), "Set version of the rrset. Default: Unix Timestamp")
      ("file,f", po::value<string>(&file), "Set path to file containing a rrset. If set, label, "
       "type, content-type, content, and version parameters will be ignored. Default is stdin(-)")
      ("encoding,e", po::value<string>(&encoding),
       "Set encoding format of input file. Default: base64")
      ("resign,r", po::value<bool>(&needResign), "Resign the input with DSK. Default is true")
      ;

    // add "Record Options" as a separate section
    options.add(config);

    po::options_description hidden("Hidden Options");
    hidden.add_options()
      ("zone", po::value<string>(&zoneStr), "host zone name")
      ("label", po::value<string>(&rrLabelStr), "label of resource record.")
      ("type", po::value<string>(&rrTypeStr), "Set the type of resource record.")
      ;

    po::positional_options_description positional;
    positional.add("zone", 1);
    positional.add("label", 1);
    positional.add("type", 1);
    positional.add("content", -1);

    po::options_description cmdlineOptions;
    cmdlineOptions.add(options).add(hidden);

    // po::options_description configFileOptions;
    // configFileOptions.add(config).add(hidden);

    po::parsed_options parsed =
      po::command_line_parser(argc, argv).options(cmdlineOptions).positional(positional).run();

    po::store(parsed, vm);
    po::notify(vm);

    if (vm.count("help")) {
      std::cout << "Usage: ndns-add-rr [options] zone label type [content ...]" << std::endl;
      std::cout << "       ndns-add-rr [options] zone [-f file] [-e raw|base64|hex]" << std::endl
                << std::endl;
      std::cout << options << std::endl;
      return 0;
    }

    if (vm.count("zone") == 0) {
      std::cerr << "Error: zone, label, and type must be specified" << std::endl;
      return 1;
    }

    if (vm.count("file") == 0) {
      if (vm.count("label") == 0) {
        std::cerr << "Error: label and type must be specified" << std::endl;
        return 1;
      }

      if (vm.count("type") == 0) {
        std::cerr << "Error: type must be specified" << std::endl;
        return 1;
      }
    }
    else {
      if (vm.count("resign"))  {
        needResign = true;
      }
      setFile = true;
    }
  }
  catch (const std::exception& ex) {
    std::cerr << "Parameter Error: " << ex.what() << std::endl;
    return 1;
  }

  try {
    Name zoneName(zoneStr);
    Name label(rrLabelStr);
    name::Component type(rrTypeStr);
    KeyChain keyChain;

    time::seconds ttl;
    if (ttlInt == -1)
      ttl = ndns::DEFAULT_CACHE_TTL;
    else
      ttl = time::seconds(ttlInt);
    uint64_t version = static_cast<uint64_t>(versionInt);

    if (setFile) {
      ndn::io::IoEncoding ioEncoding;
      if (encoding == "raw") {
        ioEncoding = ndn::io::NO_ENCODING;
      }
      else if (encoding == "hex") {
        ioEncoding = ndn::io::HEX;
      }
      else if (encoding == "base64") {
        ioEncoding = ndn::io::BASE64;
      }
      else {
        std::cerr << "Error: not supported encoding format '" << encoding
                  << "' (valid options are: raw, hex, and base64)" << std::endl;
        return 1;
      }
      ndn::ndns::ManagementTool tool(db, keyChain);
      tool.addRrsetFromFile(zoneName, file, ttl, dsk, ioEncoding, needResign);
    }
    else {
      ndns::RrsetFactory rrsetFactory(db, zoneName, keyChain, dsk);
      rrsetFactory.checkZoneKey();
      ndns::Rrset rrset;

      if (type == ndns::label::NS_RR_TYPE) {
        std::vector<Name> delegations;
        for (const auto& i : content) {
          delegations.emplace_back(i);
        }

        rrset = rrsetFactory.generateNsRrset(label,
                                             version, ttl, std::move(delegations));
      }
      else if (type == ndns::label::TXT_RR_TYPE) {
        rrset = rrsetFactory.generateTxtRrset(label,
                                              version, ttl, content);
      }

      ndn::ndns::ManagementTool tool(db, keyChain);

      if (label.size() > 1) {
        NDNS_LOG_TRACE("add multi-level label Rrset, using the same TTL as the Rrset");
        tool.addMultiLevelLabelRrset(rrset, rrsetFactory, ttl);
      }
      else {
        tool.addRrset(rrset);
      }
    }

    /// @todo Report success or failure
    //        May be also show the inserted record in ndns-list-zone format
  }
  catch (const std::exception& ex) {
    std::cerr << "Error: " << ex.what() << std::endl;
    return 1;
  }
}
