/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2018, Regents of the University of California.
 *
 * This file is part of NDN repo-ng (Next generation of NDN repository).
 * See AUTHORS.md for complete list of repo-ng authors and contributors.
 *
 * repo-ng 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.
 *
 * repo-ng 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
 * repo-ng, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * This file demonstrates how to generate data to be stored in repo with repo watch
 * protocol and repo insert protocol.
 * The details of the protocols can be find here
 *  <https://redmine.named-data.net/projects/repo-ng/wiki/Watched_Prefix_Insertion_Protocol>
 *  <https://redmine.named-data.net/projects/repo-ng/wiki/Basic_Repo_Insertion_Protocol>
 *
 * This file is used for debugging purpose. There are two modes for users to assign
 * names for the data.
 * 1)read the data name from a specific file
 * 2)input a prefix and a random version number will be added automatically
 * Users need to run nfd and repo-ng and set up specific repo protocols mentioned
 * above before running this program.
 * The description of command parameter can be found in the function usage().
 */

#include "../src/common.hpp"

#include <boost/asio/io_service.hpp>
#include <boost/lexical_cast.hpp>
#include <fstream>
#include <iostream>
#include <random>
#include <string>

namespace repo {

using ndn::time::milliseconds;

static const milliseconds DEFAULT_TIME_INTERVAL(2000);

enum Mode {
  AUTO,
  READFILE
};

class Publisher
{
public:
  class Error : public std::runtime_error
  {
  public:
    explicit
    Error(const std::string& what)
      : std::runtime_error(what)
    {
    }
  };

public:
  Publisher()
    : mode(AUTO)
    , dataPrefix(Name("/example/data"))
    , timeInterval(DEFAULT_TIME_INTERVAL)
    , duration(0)
    , m_scheduler(m_face.getIoService())
    , m_randomEngine(std::random_device{}())
    , m_randomDist(200, 1000)
    , m_range([this] { return m_randomDist(m_randomEngine); })
  {
  }

  void
  run();

  void
  autoGenerate();

  void
  generateFromFile();

  std::shared_ptr<ndn::Data>
  createData(const ndn::Name& name);

public:
  std::ifstream insertStream;
  Mode mode;
  Name dataPrefix;
  milliseconds timeInterval;
  milliseconds duration;

private:
  ndn::Face m_face;
  ndn::Scheduler m_scheduler;
  std::mt19937 m_randomEngine;
  std::uniform_int_distribution<unsigned int> m_randomDist;
  std::function<unsigned int(void)> m_range;
};

void
Publisher::run()
{
  if (mode == AUTO) {
    m_scheduler.scheduleEvent(timeInterval,
                            bind(&Publisher::autoGenerate, this));
  }
  else {
    m_scheduler.scheduleEvent(timeInterval,
                              bind(&Publisher::generateFromFile, this));
  }
  m_face.processEvents(duration);
}

void
Publisher::autoGenerate()
{
  Name name = dataPrefix;
  name.appendNumber(m_range());
  std::shared_ptr<Data> data = createData(name);
  // std::cout<<"data name = "<<data->getName()<<std::endl;
  m_face.put(*data);
  m_scheduler.scheduleEvent(timeInterval,
                            bind(&Publisher::autoGenerate, this));
}

void
Publisher::generateFromFile()
{
  if (insertStream.eof()) {
    m_face.getIoService().stop();
    return;
   }
  std::string name;
  getline(insertStream, name);
  std::shared_ptr<Data> data = createData(Name(name));
  m_face.put(*data);
  m_scheduler.scheduleEvent(timeInterval,
                            bind(&Publisher::generateFromFile, this));
}

std::shared_ptr<Data>
Publisher::createData(const Name& name)
{
  static ndn::KeyChain keyChain;
  static std::vector<uint8_t> content(1500, '-');

  std::shared_ptr<ndn::Data> data = std::make_shared<Data>();
  data->setName(name);
  data->setContent(&content[0], content.size());
  keyChain.sign(*data);
  return data;
}

static void
usage()
{
  std::cerr
      << " Publisher [-d dataPrefix] [-f filename] [-s duration time] [-t generate time interval] \n"
      << "  -d: specify the data prefix publisher generate\n"
      << "  -f: specify filename that publish would read from\n"
      << "  -s: specify the time duration of generate data\n"
      << "  -t: specify the time interval between two data generated\n"
      << std::endl;
  exit(1);
}

static int
main(int argc, char** argv)
{
  Publisher generator;
  bool isAuto = false;
  bool isRead = false;
  int opt;
  while ((opt = getopt(argc, argv, "d:f:s:t:")) != -1) {
    switch (opt) {
    case 'd':
      {
        generator.dataPrefix = Name(std::string(optarg));
        generator.mode = AUTO;
        isAuto = true;
      }
      break;
    case 'f':
      {
        isRead = true;
        generator.mode = READFILE;
        std::string str = std::string(optarg);
        generator.insertStream.open(str.c_str());
         if (!generator.insertStream.is_open()) {
          std::cerr << "ERROR: cannot open " << std::string(optarg) << std::endl;
          return 1;
        }
      }
      break;
    case 's':
      try {
        generator.duration = milliseconds(boost::lexical_cast<uint64_t>(optarg));
      }
      catch (const boost::bad_lexical_cast&) {
        std::cerr << "-s option should be an integer.";
        return 1;
      }
      break;
    case 't':
      try {
        generator.timeInterval = milliseconds(boost::lexical_cast<uint64_t>(optarg));
      }
      catch (const boost::bad_lexical_cast&) {
        std::cerr << "-t option should be an integer.";
        return 1;
      }
      break;
    default:
      usage();
      break;
    }
  }

  argc -= optind;
  argv += optind;

  if (argc != 0)
    usage();

  if (isAuto && isRead)
    usage();

  generator.run();
  return 0;
}

} // namespace repo

int
main(int argc, char** argv)
{
  try {
    return repo::main(argc, argv);
  }
  catch (const std::exception& e) {
    std::cerr << "ERROR: " << e.what() << std::endl;
    return 2;
  }
}
