/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
 * Copyright (C) 2014 University of Arizona.
 *
 * GNU 3.0 License, see the LICENSE file for more information
 *
 * Author: Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
 */

#include <sstream>

#include <boost/asio.hpp>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/noncopyable.hpp>

#include <ndn-cxx/face.hpp>
#include <ndn-cxx/security/key-chain.hpp>

#include "logger.hpp"

namespace ndn {

class NdnTrafficServer : boost::noncopyable
{
public:

  explicit
  NdnTrafficServer(char* programName)
    : m_logger("NdnTrafficServer")
    , m_programName(programName)
    , m_hasError(false)
    , m_hasQuietLogging(false)
    , m_nRegistrationsFailed(0)
    , m_nMaximumInterests(-1)
    , m_nInterestsReceived(0)
    , m_contentDelay(time::milliseconds(-1))
    , m_ioService(new boost::asio::io_service)
    , m_face(m_ioService)
  {
    m_instanceId = boost::lexical_cast<std::string>(std::rand());
  }

  class DataTrafficConfiguration
  {
  public:
    DataTrafficConfiguration()
      : m_contentType(-1)
      , m_freshnessPeriod(time::milliseconds(-1))
      , m_contentBytes(-1)
      , m_contentDelay(time::milliseconds(-1))
      , m_nInterestsReceived(0)
    {
    }

    void
    printTrafficConfiguration(Logger& logger)
    {
      std::string detail = "";
      if (m_name != "")
        detail += "Name=" + m_name + ", ";
      if (m_contentType >= 0)
        detail += "ContentType=" + boost::lexical_cast<std::string>(m_contentType) + ", ";
      if (m_freshnessPeriod >= time::milliseconds(0))
        detail += "FreshnessPeriod=" +
          boost::lexical_cast<std::string>(static_cast<int>(m_freshnessPeriod.count())) + ", ";
      if (m_contentBytes >= 0)
        detail += "ContentBytes=" + boost::lexical_cast<std::string>(m_contentBytes) + ", ";
      if (m_contentDelay >= time::milliseconds(0))
        detail += "ContentDelay=" +
          boost::lexical_cast<std::string>(m_contentDelay.count()) + ", ";
      if (m_content != "")
        detail += "Content=" + m_content + ", ";
      if (detail.length() >= 2)
        detail = detail.substr(0, detail.length() - 2);
      logger.log(detail, false, false);
    }


    bool
    extractParameterValue(const std::string& detail,
                          std::string& parameter,
                          std::string& value)
    {
      std::string allowedCharacters = ":/+._-%";
      parameter = "";
      value = "";
      int i = 0;
      while (detail[i] != '=' && i < detail.length())
        {
          parameter += detail[i];
          i++;
        }
      if (i == detail.length())
        return false;
      i++;
      while ((std::isalnum(detail[i]) ||
              allowedCharacters.find(detail[i]) != std::string::npos) &&
              i < detail.length())
        {
          value += detail[i];
          i++;
        }
      if(parameter == "" || value == "")
        return false;
      return true;
    }

    bool
    processConfigurationDetail(const std::string& detail,
                               Logger& logger,
                               int lineNumber)
    {
      std::string parameter, value;
      if (extractParameterValue(detail, parameter, value))
        {
          if (parameter == "Name")
            m_name = value;
          else if (parameter == "ContentType")
            m_contentType = boost::lexical_cast<int>(value);
          else if (parameter == "FreshnessPeriod")
            m_freshnessPeriod = time::milliseconds(boost::lexical_cast<int>(value));
          else if (parameter == "ContentDelay")
            m_contentDelay = time::milliseconds(boost::lexical_cast<int>(value));
          else if (parameter == "ContentBytes")
            m_contentBytes = boost::lexical_cast<int>(value);
          else if (parameter == "Content")
            m_content = value;
          else
            logger.log("Line " + boost::lexical_cast<std::string>(lineNumber) +
                       " \t- Invalid Parameter='" + parameter + "'", false, true);
        }
      else
        {
          logger.log("Line " + boost::lexical_cast<std::string>(lineNumber) +
            " \t- Improper Traffic Configuration Line - " + detail, false, true);
          return false;
        }
      return true;
    }

    bool
    checkTrafficDetailCorrectness()
    {
      return true;
    }

    std::string m_name;
    int m_contentType;
    time::milliseconds m_freshnessPeriod;
    int m_contentBytes;
    time::milliseconds m_contentDelay;
    std::string m_content;
    int m_nInterestsReceived;

  };

  void
  usage()
  {

    std::cout << "\nUsage: " << m_programName << " [options] <Traffic_Configuration_File>\n"
      "Respond to Interest as per provided Traffic Configuration File\n"
      "Multiple Prefixes can be configured for handling.\n"
      "Set environment variable NDN_TRAFFIC_LOGFOLDER for redirecting output to a log.\n"
      "  [-d interval] - set delay before responding to interest in milliseconds\n"
      "  [-c count]    - specify maximum number of interests to be satisfied\n"
      "  [-q]          - quiet logging - no interest reception/data generation messages\n"
      "  [-h]          - print help and exit\n\n";
    exit(1);

  }

  void
  setMaximumInterests(int maximumInterests)
  {
    if (maximumInterests < 0)
      usage();
    m_nMaximumInterests = maximumInterests;
  }

  bool
  hasError() const
  {
    return m_hasError;
  }

  void
  setContentDelay(int contentDelay)
  {
    if (contentDelay < 0)
      usage();
    m_contentDelay = time::milliseconds(contentDelay);
  }

  void
  setConfigurationFile(char* configurationFile)
  {
    m_configurationFile = configurationFile;
  }

  void
  setQuietLogging()
  {
    m_hasQuietLogging = true;
  }

  void
  signalHandler()
  {
    logStatistics();
    m_logger.shutdownLogger();
    m_face.shutdown();
    m_ioService->stop();
    if (m_hasError)
      exit(1);
    else
      exit(0);
  }

  void
  logStatistics()
  {
    m_logger.log("\n\n== Interest Traffic Report ==\n", false, true);
    m_logger.log("Total Traffic Pattern Types = " +
      boost::lexical_cast<std::string>(m_trafficPatterns.size()), false, true);
    m_logger.log("Total Interests Received    = " +
      boost::lexical_cast<std::string>(m_nInterestsReceived), false, true);
    if (m_nInterestsReceived < m_nMaximumInterests)
      m_hasError = true;
    for (int patternId = 0; patternId < m_trafficPatterns.size(); patternId++)
      {
        m_logger.log("\nTraffic Pattern Type #" +
          boost::lexical_cast<std::string>(patternId + 1), false, true);
        m_trafficPatterns[patternId].printTrafficConfiguration(m_logger);
        m_logger.log("Total Interests Received    = " +
          boost::lexical_cast<std::string>(
            m_trafficPatterns[patternId].m_nInterestsReceived) + "\n", false, true);
      }
  }

  bool
  checkTrafficPatternCorrectness()
  {
    return true;
  }

  void
  parseConfigurationFile()
  {
    std::string patternLine;
    std::ifstream patternFile;
    m_logger.log("Analyzing Traffic Configuration File: " + m_configurationFile, true, true);
    patternFile.open(m_configurationFile.c_str());
    if (patternFile.is_open())
      {
        int patternId = 0;
        int lineNumber = 0;
        while (getline(patternFile, patternLine))
          {
            lineNumber++;
            if (std::isalpha(patternLine[0]))
              {
                DataTrafficConfiguration dataData;
                bool shouldSkipLine = false;
                patternId++;
                if (dataData.processConfigurationDetail(patternLine, m_logger, lineNumber))
                  {
                    while (getline(patternFile, patternLine) && std::isalpha(patternLine[0]))
                      {
                        lineNumber++;
                        if (!dataData.processConfigurationDetail(patternLine,
                                                                 m_logger,
                                                                 lineNumber))
                          {
                            shouldSkipLine = true;
                            break;
                          }
                      }
                    lineNumber++;
                  }
                else
                  shouldSkipLine = true;
                if (!shouldSkipLine)
                  {
                    if (dataData.checkTrafficDetailCorrectness())
                      m_trafficPatterns.push_back(dataData);
                  }
              }
          }
        patternFile.close();
        if (!checkTrafficPatternCorrectness())
          {
            m_logger.log("ERROR - Traffic Configuration Provided Is Not Proper- " +
                         m_configurationFile, false, true);
            m_logger.shutdownLogger();
            exit(1);
          }
        m_logger.log("Traffic Configuration File Processing Completed\n", true, false);
        for (patternId = 0; patternId < m_trafficPatterns.size(); patternId++)
          {
            m_logger.log("Traffic Pattern Type #" +
              boost::lexical_cast<std::string>(patternId + 1), false, false);
            m_trafficPatterns[patternId].printTrafficConfiguration(m_logger);
            m_logger.log("", false, false);
          }
      }
    else
      {
        m_logger.log("ERROR - Unable To Open Traffic Configuration File: " +
          m_configurationFile, false, true);
        m_logger.shutdownLogger();
        exit(1);
      }
  }

  void
  initializeTrafficConfiguration()
  {
    if (boost::filesystem::exists(boost::filesystem::path(m_configurationFile)))
      {
        if (boost::filesystem::is_regular_file(boost::filesystem::path(m_configurationFile)))
          {
            parseConfigurationFile();
          }
        else
          {
            m_logger.log("ERROR - Traffic Configuration File Is Not A Regular File: " +
              m_configurationFile, false, true);
            m_logger.shutdownLogger();
            exit(1);
          }
      }
    else
      {
        m_logger.log("ERROR - Traffic Configuration File Does Not Exist: " +
          m_configurationFile, false, true);
        m_logger.shutdownLogger();
        exit(1);
      }
  }

  static std::string
  getRandomByteString(int randomSize)
  {
    std::string randomString;
    for (int i = 0; i < randomSize; i++)
      randomString += static_cast<char>(std::rand() % 128);
    return randomString;
  }

  void
  onInterest(const Name& name, const Interest& interest, int patternId)
  {
    if (m_nMaximumInterests < 0 || m_nInterestsReceived < m_nMaximumInterests)
      {
        Data data(interest.getName());

        if (m_trafficPatterns[patternId].m_contentType >= 0)
          data.setContentType(m_trafficPatterns[patternId].m_contentType);

        if (m_trafficPatterns[patternId].m_freshnessPeriod >= time::milliseconds(0))
          data.setFreshnessPeriod(m_trafficPatterns[patternId].m_freshnessPeriod);

        std::string content = "";
        if (m_trafficPatterns[patternId].m_contentBytes >= 0)
          content = getRandomByteString(m_trafficPatterns[patternId].m_contentBytes);
        if (m_trafficPatterns[patternId].m_content != "")
          content = m_trafficPatterns[patternId].m_content;

        data.setContent(reinterpret_cast<const uint8_t*>(content.c_str()), content.length());
        m_keyChain.sign(data);
        m_nInterestsReceived++;
        m_trafficPatterns[patternId].m_nInterestsReceived++;
        std::string logLine = "Interest Received          - PatternType=" +
          boost::lexical_cast<std::string>(patternId + 1);
        logLine += ", GlobalID=" + boost::lexical_cast<std::string>(m_nInterestsReceived);
        logLine += ", LocalID=" +
          boost::lexical_cast<std::string>(m_trafficPatterns[patternId].m_nInterestsReceived);
        logLine += ", Name=" + m_trafficPatterns[patternId].m_name;
        if (!m_hasQuietLogging)
          m_logger.log(logLine, true, false);
        if (m_trafficPatterns[patternId].m_contentDelay > time::milliseconds(-1))
          usleep(m_trafficPatterns[patternId].m_contentDelay.count() * 1000);
        if (m_contentDelay > time::milliseconds(-1))
          usleep(m_contentDelay.count() * 1000);
        m_face.put(data);
      }
    if (m_nMaximumInterests >= 0 && m_nInterestsReceived == m_nMaximumInterests)
      {
        logStatistics();
        m_logger.shutdownLogger();
        m_face.shutdown();
        m_ioService->stop();
      }
  }

  void
  onRegisterFailed(const ndn::Name& prefix, const std::string& reason, int patternId)
  {
    std::string logLine = "";
    logLine += "Prefix Registration Failed - PatternType=" +
      boost::lexical_cast<std::string>(patternId + 1);
    logLine += ", Name=" + m_trafficPatterns[patternId].m_name;
    m_logger.log(logLine, true, true);
    m_nRegistrationsFailed++;
    if (m_nRegistrationsFailed == m_trafficPatterns.size())
      {
        m_hasError = true;
        signalHandler();
      }
  }

  void
  run()
  {
    boost::asio::signal_set signalSet(*m_ioService, SIGINT, SIGTERM);
    signalSet.async_wait(boost::bind(&NdnTrafficServer::signalHandler, this));
    m_logger.initializeLog(m_instanceId);
    initializeTrafficConfiguration();
    if (m_nMaximumInterests == 0)
      {
        logStatistics();
        m_logger.shutdownLogger();
        return;
      }

    for (int patternId = 0; patternId < m_trafficPatterns.size(); patternId++)
      {
        m_face.setInterestFilter(m_trafficPatterns[patternId].m_name,
                                 bind(&NdnTrafficServer::onInterest,
                                      this, _1, _2,
                                      patternId),
                                 bind(&NdnTrafficServer::onRegisterFailed,
                                      this, _1, _2,
                                      patternId));
      }

    try {
      m_face.processEvents();
    }
    catch (std::exception& e) {
      m_logger.log("ERROR: " + static_cast<std::string>(e.what()), true, true);
      m_logger.shutdownLogger();
      m_hasError = true;
      m_ioService->stop();
    }
  }

private:
  KeyChain m_keyChain;
  std::string m_programName;
  bool m_hasError;
  bool m_hasQuietLogging;
  std::string m_instanceId;
  time::milliseconds m_contentDelay;
  int m_nRegistrationsFailed;
  Logger m_logger;
  std::string m_configurationFile;
  shared_ptr<boost::asio::io_service> m_ioService;
  Face m_face;
  std::vector<DataTrafficConfiguration> m_trafficPatterns;
  int m_nMaximumInterests;
  int m_nInterestsReceived;
};

} // namespace ndn

int
main(int argc, char* argv[])
{
  std::srand(std::time(0));
  ndn::NdnTrafficServer ndnTrafficServer(argv[0]);
  int option;
  while ((option = getopt(argc, argv, "hqc:d:")) != -1) {
    switch (option) {
    case 'h':
      ndnTrafficServer.usage();
      break;
    case 'c':
      ndnTrafficServer.setMaximumInterests(atoi(optarg));
      break;
    case 'd':
      ndnTrafficServer.setContentDelay(atoi(optarg));
      break;
    case 'q':
      ndnTrafficServer.setQuietLogging();
      break;
    default:
      ndnTrafficServer.usage();
      break;
    }
  }

  argc -= optind;
  argv += optind;

  if (argv[0] == 0)
    ndnTrafficServer.usage();

  ndnTrafficServer.setConfigurationFile(argv[0]);
  ndnTrafficServer.run();

  if (ndnTrafficServer.hasError())
    return 1;
  else
    return 0;
}
