/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2020, 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 "clients/response.hpp"
#include "clients/query.hpp"
#include "ndns-label.hpp"
#include "validator/validator.hpp"
#include "ndns-enum.hpp"
#include "ndns-tlv.hpp"
#include "logger.hpp"
#include "daemon/db-mgr.hpp"
#include "util/util.hpp"
#include "util/cert-helper.hpp"

#include <ndn-cxx/security/key-chain.hpp>
#include <ndn-cxx/security/signing-helpers.hpp>
#include <ndn-cxx/data.hpp>
#include <ndn-cxx/util/io.hpp>
#include <ndn-cxx/util/regex.hpp>
#include <ndn-cxx/encoding/block.hpp>
#include <ndn-cxx/encoding/block-helpers.hpp>
#include <boost/noncopyable.hpp>
#include <boost/program_options.hpp>
#include <boost/asio.hpp>
#include <boost/filesystem.hpp>

#include <string>
#include <tuple>

namespace ndn {
namespace ndns {

NDNS_LOG_INIT(NdnsUpdate);

class NdnsUpdate : noncopyable
{
public:
  NdnsUpdate(const Name& zone, const shared_ptr<Data>& update, Face& face)
    : m_zone(zone)
    , m_interestLifetime(DEFAULT_INTEREST_LIFETIME)
    , m_face(face)
    , m_validator(NdnsValidatorBuilder::create(face))
    , m_update(update)
    , m_hasError(false)
  {
  }

  void
  start()
  {
    NDNS_LOG_INFO(" ================ "
                  << "start to update RR at Zone = " << this->m_zone
                  << " new RR is: " << m_update->getName()
                  <<" =================== ");
    NDNS_LOG_INFO("new RR is signed by: " << m_update->getKeyLocator()->getName());

    Interest interest = this->makeUpdateInterest();
    NDNS_LOG_TRACE("[* <- *] send Update: " << m_update->getName().toUri());
    m_face.expressInterest(interest,
                           bind(&NdnsUpdate::onData, this, _1, _2),
                           bind(&NdnsUpdate::onTimeout, this, _1), // nack
                           bind(&NdnsUpdate::onTimeout, this, _1) //dynamic binding
                           );
  }

  void
  stop()
  {
    m_face.getIoService().stop();
  }

private:
  void
  onData(const Interest&, const Data& data)
  {
    NDNS_LOG_INFO("get response of Update");
    int ret = -1;
    std::string msg;
    std::tie(ret, msg) = this->parseResponse(data);
    NDNS_LOG_INFO("Return Code: " << ret << ", and Update "
                  << (ret == UPDATE_OK ? "succeeds" : "fails"));
    if (ret != UPDATE_OK)
      m_hasError = true;

    if (!msg.empty()) {
      NDNS_LOG_INFO("Return Msg: " << msg);
    }

    NDNS_LOG_INFO("to verify the response");
    m_validator->validate(data,
                          bind(&NdnsUpdate::onDataValidated, this, _1),
                          bind(&NdnsUpdate::onDataValidationFailed, this, _1, _2));
  }

  std::tuple<int, std::string>
  parseResponse(const Data& data)
  {
    int ret = -1;
    std::string msg;
    Block blk = data.getContent();
    blk.parse();
    Block block = blk.blockFromValue();
    block.parse();
    auto val = block.elements_begin();
    for (; val != block.elements_end(); ++val) {
      if (val->type() == ndns::tlv::UpdateReturnCode) { // the first must be return code
        ret = readNonNegativeInteger(*val);
      }
      else if (val->type() == ndns::tlv::UpdateReturnMsg) {
        msg =  std::string(reinterpret_cast<const char*>(val->value()), val->value_size());
      }
    }

    return std::make_tuple(ret, msg);
  }

  /**
   * @brief construct a query (interest) which contains the update information
   */
  Interest
  makeUpdateInterest()
  {
    Query q(m_zone, label::NDNS_ITERATIVE_QUERY);
    q.setRrLabel(Name().append(m_update->wireEncode()));
    q.setRrType(label::NDNS_UPDATE_LABEL);
    q.setInterestLifetime(m_interestLifetime);

    return q.toInterest();
  }

private:
  void
  onTimeout(const ndn::Interest&)
  {
    NDNS_LOG_TRACE("Update timeout");
    m_hasError = true;
    this->stop();
  }

  void
  onDataValidated(const Data&)
  {
    NDNS_LOG_INFO("data pass verification");
    this->stop();
  }

  void
  onDataValidationFailed(const Data&, const security::v2::ValidationError&)
  {
    NDNS_LOG_INFO("data does not pass verification");
    m_hasError = true;
    this->stop();
  }

public:
  void
  setInterestLifetime(const time::milliseconds& interestLifetime)
  {
    m_interestLifetime = interestLifetime;
  }

  bool
  hasError() const
  {
    return m_hasError;
  }

private:
  Name m_zone;

  time::milliseconds m_interestLifetime;

  Face& m_face;
  unique_ptr<security::v2::Validator> m_validator;
  KeyChain m_keyChain;

  shared_ptr<Data> m_update;
  bool m_hasError;
};

} // namespace ndns
} // namespace ndn

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

  Name zone;
  int ttl = 4;
  Name rrLabel;
  string rrType = "TXT";
  string contentTypeStr = "resp";
  Name certName;
  std::vector<string> contents;
  string contentFile;
  shared_ptr<Data> update;

  try {
    namespace po = boost::program_options;
    po::variables_map vm;

    po::options_description generic("Generic Options");
    generic.add_options()("help,h", "print help message");

    po::options_description config("Configuration");
    config.add_options()
      ("ttl,T", po::value<int>(&ttl), "TTL of query. default: 4 sec")
      ("rrtype,t", po::value<string>(&rrType), "set request RR Type. default: TXT")
      ("contentType,n", po::value<string>(&contentTypeStr), "Set the contentType of the resource record. "
       "Potential values are [blob|link|nack|auth|resp]. Default: resp")
      ("cert,c", po::value<Name>(&certName), "set the name of certificate to sign the update")
      ("content,o", po::value<std::vector<string>>(&contents)->multitoken(),
       "set the content of the RR")
      ("contentFile,f", po::value<string>(&contentFile), "set the path of file which contain"
       " Response packet in base64 format")
      ;

    po::options_description hidden("Hidden Options");
    hidden.add_options()
      ("zone,z", po::value<Name>(&zone), "zone the record is delegated")
      ("rrlabel,l", po::value<Name>(&rrLabel), "set request RR Label")
      ;
    po::positional_options_description postion;
    postion.add("zone", 1);
    postion.add("rrlabel", 1);

    po::options_description cmdline_options;
    cmdline_options.add(generic).add(config).add(hidden);

    po::options_description config_file_options;
    config_file_options.add(config).add(hidden);

    po::options_description visible("Usage: ndns-update zone rrLabel [-t rrType] [-T TTL] "
                                    "[-n NdnsContentType] [-c cert] "
                                    "[-f contentFile]|[-o content]\n"
                                    "Allowed options");

    visible.add(generic).add(config);

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

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

    if (vm.count("help")) {
      std::cout << visible << std::endl;
      return 0;
    }


    if (vm.count("content") && vm.count("contentFile")) {
      std::cerr << "both -o content and -f contentFile are set. Only one is allowed" << std::endl;
      return 1;
    }

    if (!vm.count("contentFile")) {
      NDNS_LOG_TRACE("content option is set. try to figure out the certificate");
      if (!vm.count("zone") || !vm.count("rrlabel")) {
        std::cerr << "-o option must be set together with -z zone and -r rrLabel" << std::endl;
        return 1;
      }

      KeyChain keyChain;
      if (certName.empty()) {
        Name name = Name().append(zone).append(rrLabel);
        // choosing the longest match of the identity who also have default certificate
        for (size_t i = name.size() + 1; i > 0; --i) { // i >=0 will present warnning
          Name tmp = name.getPrefix(i - 1);
          if (CertHelper::doesIdentityExist(keyChain, tmp)) {
            try {
              certName = CertHelper::getDefaultCertificateNameOfIdentity(keyChain, tmp);
              break;
            }
            catch (const std::exception&) {
              // If it cannot get a default certificate from one identity,
              // just ignore this one try next identity.
              ;
            }
          }
        } // for

        if (certName.empty()) {
          std::cerr << "cannot figure out the certificate automatically. "
                    << "please set it with -c CERT_NAEME" << std::endl;
          return 1;
        }
      }

      NdnsContentType contentType = toNdnsContentType(contentTypeStr);

      if (contentType == ndns::NDNS_UNKNOWN) {
        std::cerr << "unknown NdnsContentType: " << contentTypeStr << std::endl;
        return 1;
      }

      Response re;
      re.setZone(zone);
      re.setRrLabel(rrLabel);
      name::Component qType = ndns::label::NDNS_ITERATIVE_QUERY;

      re.setQueryType(qType);
      re.setRrType(name::Component(rrType));
      re.setContentType(contentType);

      for (const auto& content : contents) {
        re.addRr(makeBinaryBlock(ndns::tlv::RrData, content.c_str(), content.size()));

        // re.addRr(content);
      }

      update = re.toData();
      keyChain.sign(*update, security::signingByCertificate(certName));
    }
    else {
      try {
        update = ndn::io::load<ndn::Data>(contentFile);
        NDNS_LOG_TRACE("load data " << update->getName() << " from content file: " << contentFile);
      }
      catch (const std::exception& e) {
        std::cerr << "Error: load Data packet from file: " << contentFile
                  << ". Due to: " << e.what() << std::endl;
        return 1;
      }

      try {
        // must check the Data is a legal Response with right name
        shared_ptr<Regex> regex = make_shared<Regex>("(<>*)<NDNS>(<>+)<CERT><>*");
        shared_ptr<Regex> regex2 = make_shared<Regex>("(<>*)<NDNS>(<>+)");

        Name zone2;
        if (regex->match(update->getName())) {
          zone2 = regex->expand("\\1");
        }
        else if (regex2->match(update->getName())) {
          zone2 = regex2->expand("\\1");
        }
        else {
          std::cerr << "The loaded Data packet cannot be stored in NDNS "
            "since its does not have a proper name" << std::endl;
          return 1;
        }

        if (vm.count("zone") && zone != zone2) {
          std::cerr << "The loaded Data packet is supposed to be stored at zone: " << zone2
                    << " instead of zone: " << zone << std::endl;
          return 1;
        }
        else {
          zone = zone2;
        }

        Response re;
        re.fromData(zone, *update);

        if (vm.count("rrlabel") && rrLabel != re.getRrLabel()) {
          std::cerr << "The loaded Data packet is supposed to have rrLabel: " << re.getRrLabel()
                    << " instead of label: " << rrLabel << std::endl;
          return 1;
        }

        if (vm.count("rrtype") && name::Component(rrType) != re.getRrType()) {
          std::cerr << "The loaded Data packet is supposed to have rrType: " << re.getRrType()
                    << " instead of label: " << rrType << std::endl;
          return 1;
        }
      }
      catch (const std::exception& e) {
        std::cerr << "Error: the loaded Data packet cannot parse to a Response stored at zone: "
                  << zone << std::endl;
        return 1;
      }

    }
  }
  catch (const std::exception& ex) {
    std::cerr << "Parameter Error: " << ex.what() << std::endl;
    return 1;
  }

  Face face;
  try {
    NdnsUpdate updater(zone, update, face);
    updater.setInterestLifetime(ndn::time::seconds(ttl));

    updater.start();
    face.processEvents();
    if (updater.hasError())
      return 1;
    else
      return 0;
  }
  catch (const std::exception& e) {
    std::cerr << "Error: " << e.what() << std::endl;
    return 1;
  }
}
