#include <log4cxx/logger.h>
#include <log4cxx/basicconfigurator.h>
#include <log4cxx/propertyconfigurator.h>
#include <log4cxx/xml/domconfigurator.h>

#include "options.h"

#include <boost/program_options/option.hpp>
#include <boost/program_options/positional_options.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options/parsers.hpp>
#include "xtreme/common/event_frame.h"
#include "xtreme/common/timestamp.h"
#include "xtreme/common/TcpEngine/ITcpMeasure.h"
#include "xtreme/common/internal/TcpEngine/logger.h"
#include "TcpEngineThread.h"

using namespace xtreme::TcpEngine;
namespace po = boost::program_options;

int init_options(int argc, char* argv[]) {
  xtreme::TcpEngine::Logger::trace_enabled_ = false;
  xtreme::TcpEngine::Logger::debug_enabled_ = false;

  try {
    static po::options_description desc("Allowed options");
    desc.add_options()("help", "produce help message")("input-pcap, I", po::value<std::vector<std::string> >(),
                                                       "select the input pcap file name, without path")(
        "pcap-path, P", po::value<std::string>(), "select path of input pcap")(
        "streams, P", po::value<uint32_t>(), "number of streams")(
        "share_mode, P", po::value<bool>(), "true: Engine thread is same as the napa acquiziation thread; otherwize, use seperate thread")(
        "zero_copy, P", po::value<bool>(), "true: not copy the napa packet into mri, that is DMA mode;otherwise, copy the packet payload to form framevent used in mri")(
        "upp_streams, P", po::value<uint32_t>(), "number of upp streams")(
        "core_per_cpu, P", po::value<uint32_t>(), "number of cores per cpu.")(
        "enable-tcp, E", po::value<bool>(), "true for enable TCP Engine; otherwise packet won't go into TcpEngine")(
        "counter-flags, C", po::value<uint32_t>(),
        "input the counter combination testing flags,0:all;1:accessiblity KPI;2:Integrity KPI")(
        "logconfig_xml, l", po::value<std::string>(), "select full path name of log config-xml")(
        "show-result", po::value<bool>(), "true: print out the measure result; otherwise not print")(
        "lru-size", po::value<uint32_t>(), "the size of lru cache, default 1M, ")(
        "acked-size", po::value<uint32_t>(), "the size of lru cache, default 200, ")(
        "unacked-size", po::value<uint32_t>(), "the size of lru cache, default 200, ")(
        "lru-threshold", po::value<uint32_t>(), "batch aging size for lru, default 20000, ")(
        "use_cpu_core", po::value<uint32_t>(), "select running on cpu core, default 20, ")(
        "loop_pcap", po::value<uint32_t>(),
        "If 0, looping is indefinite; otherwise, it last number of times and then stop.  , default loop=1 times, ")(
        "time_wait", po::value<uint32_t>(),
        "pcap repaly will wait tcpEngine for process if latter can't keep pace with pcap replay, default is 10ms ")(
        "max_queue", po::value<uint32_t>(), "maximu queue size of passing packets to TcpEngine,d efal is 100000")(
        "engine-speed", po::value<bool>(),
        "true: measure engine thruput, false: not measure engine speed besides of overall thruput, defaul true ")(
        "enable-csv", po::value<bool>(), "true: enable the csv file; otherwise, no csv file output ")(
        "test_napa", po::value<bool>(), "true: just run test function to napa card; otherwise, run harness to TcpEngine");

    po::positional_options_description p;
    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);
    if (vm.count("help") || vm.size() < 1) {
      std::cout << "command options:" << std::endl;
      std::cout << desc;
      return 0;
    }
    if (vm.count("input-pcap")) {
      xtreme::iwf::get_option().arrPcap = vm["input-pcap"].as<std::vector<std::string> >();
    }
    if (vm.count("pcap-path")) {
      xtreme::iwf::get_option().pcapPath = vm["pcap-path"].as<std::string>();
    }
    if (vm.count("enable-tcp")) {
      xtreme::iwf::get_option().enableTcpEngine = vm["enable-tcp"].as<bool>();
    }
    if (vm.count("counter-flags")) {
      xtreme::iwf::get_option().counterFlags = vm["counter-flags"].as<uint32_t>();
    }

    if (vm.count("show-result")) {
      xtreme::iwf::get_option().show_result = vm["show-result"].as<bool>();
    } else {
      xtreme::iwf::get_option().show_result = true;
    }
    if (vm.count("logconfig_xml")) {
      xtreme::iwf::get_option().logconfig_xml = vm["logconfig_xml"].as<std::string>();
    }
    if (vm.count("acked-size")) {
      xtreme::ITcpMeasure::options().retrx_ack_table_size = vm["acked-size"].as<uint32_t>();
    }
    if (vm.count("unacked-size")) {
      xtreme::ITcpMeasure::options().max_unacked = vm["acked-size"].as<uint32_t>();
    }
    if (vm.count("lru-size")) {
      xtreme::ITcpMeasure::options().lru_cache_size = vm["lru-size"].as<uint32_t>();
    }
    if (vm.count("lru-threshold")) {
      xtreme::ITcpMeasure::options().lru_cache_throttle_threshold_ = vm["lru-threshold"].as<uint32_t>();
    }
    log4cxx::xml::DOMConfigurator::configure(xtreme::iwf::get_option().logconfig_xml);

    if (vm.count("enable-csv")) {
      xtreme::ITcpMeasure::options().csv_enable = vm["enable-csv"].as<bool>();
      ITcpMeasure::options().strCSV_Path = "/var/log/mri";
    }

    if (xtreme::iwf::get_option().enableTcpEngine) {
      xtreme::ITcpMeasure::options().enable = true;
      xtreme::ITcpMeasure::options().telemetry = true;
    }
    std::cout << "enable tcp=" << xtreme::ITcpMeasure::options().enable << std::endl;

    if (vm.count("time_wait")) {
      xtreme::iwf::get_option().time_wait = vm["time_wait"].as<uint32_t>();
    }

    if (vm.count("max_queue")) {
      xtreme::iwf::get_option().max_queue = vm["max_queue"].as<uint32_t>();
    }

    if (vm.count("use_cpu_core")) {
      xtreme::iwf::get_option().cpu_core = vm["use_cpu_core"].as<uint32_t>();
    }
    if (vm.count("loop_pcap")) {
      xtreme::iwf::get_option().loop_pcap = vm["loop_pcap"].as<uint32_t>();
    }

    if (vm.count("engine-speed")) {
      xtreme::iwf::get_option().measure_engine = vm["engine-speed"].as<bool>();
      xtreme::ITcpMeasure::options().engine_speed = vm["engine-speed"].as<bool>();
    } else {
      xtreme::iwf::get_option().measure_engine = true;
      xtreme::ITcpMeasure::options().engine_speed = true;
    }

    if (vm.count("streams")) {
      xtreme::iwf::get_option().streams = vm["streams"].as<uint32_t>();
    } else {
      xtreme::iwf::get_option().streams = 16;
    }
    if (vm.count("upp_streams")) {
      xtreme::iwf::get_option().upp_streams = vm["upp_streams"].as<uint32_t>();
    } else {
      xtreme::iwf::get_option().upp_streams = 15;
    }
    if (vm.count("core_per_cpu")) {
      xtreme::iwf::get_option().core_per_cpu = vm["core_per_cpu"].as<uint32_t>();
    } else {
      xtreme::iwf::get_option().core_per_cpu = 1;
    }
    if (vm.count("test_napa")) {
      xtreme::iwf::get_option().napa_test = vm["test_napa"].as<bool>();
    } else {
      xtreme::iwf::get_option().napa_test = false;
    }
    if (vm.count("zero_copy")) {
      xtreme::iwf::get_option().zero_copy = vm["zero_copy"].as<bool>();
    } else {
      xtreme::iwf::get_option().zero_copy = false;
    }

    xtreme::ITcpMeasure::options().engine_speed = false;
    std::cout << "[engine_speed]-----------:" << (xtreme::iwf::get_option().measure_engine ? "on" : "off") << std::endl;
    std::cout << "[telementry]-------------:" << (xtreme::ITcpMeasure::options().telemetry ? "on" : "off") << std::endl;
    std::cout << "[max_queue]--------------:" << xtreme::iwf::get_option().max_queue << std::endl;
    std::cout << "[time_wait]--------------:" << xtreme::iwf::get_option().time_wait << " ms" << std::endl;
    std::cout << "[loop pcap]--------------:" << xtreme::iwf::get_option().loop_pcap << std::endl;
    std::cout << "[streams]----------------:" << xtreme::iwf::get_option().streams << std::endl;
    std::cout << "[upp_streams]------------:" << xtreme::iwf::get_option().upp_streams << std::endl;
    std::cout << "[core_per_cpu]-----------:" << xtreme::iwf::get_option().core_per_cpu << std::endl;
    std::cout << "[test_napa]--------------:" << (xtreme::iwf::get_option().napa_test ? "yes" : "no") << std::endl;
    std::cout << "[zero_copy]--------------:" << (xtreme::iwf::get_option().zero_copy ? "yes" : "no") << std::endl;
  } catch (...) {
    return -1;
  }
  return 0;
}

static int g_interrupt_count = 0;
int get_interrupt_count() {
  return g_interrupt_count;
}

void signal_handler(int ) {
  ++g_interrupt_count;
  TCP_MSG_INFO("signal_handler: g_interrupt_count=%d", g_interrupt_count);
}
/*
 * options.cc
 *
 *  Created on: Feb 5, 2014
 *      Author: root
 */

#include <log4cxx/logger.h>
#include <log4cxx/basicconfigurator.h>
#include <log4cxx/propertyconfigurator.h>
#include <log4cxx/xml/domconfigurator.h>

#include "options.h"

#include <boost/program_options/option.hpp>
#include <boost/program_options/positional_options.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options/parsers.hpp>
#include "xtreme/common/event_frame.h"
#include "xtreme/common/timestamp.h"
#include "xtreme/common/TcpEngine/ITcpMeasure.h"
#include "xtreme/common/internal/TcpEngine/logger.h"
#include "TcpEngineThread.h"



using namespace xtreme::TcpEngine;
namespace po = boost::program_options;

int init_options(int argc, char* argv[]) {
  xtreme::TcpEngine::Logger::trace_enabled_ = false;
  xtreme::TcpEngine::Logger::debug_enabled_ = false;

  try {
    static po::options_description desc("Allowed options");
    desc.add_options()("help", "produce help message")("input-pcap, I", po::value<std::vector<std::string> >(),
                                                       "select the input pcap file name, without path")(
        "pcap-path, P", po::value<std::string>(), "select path of input pcap")(
        "streams, P", po::value<uint32_t>(), "number of streams")(
        "share_mode, P", po::value<bool>(), "true: Engine thread is same as the napa acquiziation thread; otherwize, use seperate thread")(
        "zero_copy, P", po::value<bool>(), "true: not copy the napa packet into mri, that is DMA mode;otherwise, copy the packet payload to form framevent used in mri")(
        "upp_streams, P", po::value<uint32_t>(), "number of upp streams")(
        "core_per_cpu, P", po::value<uint32_t>(), "number of cores per cpu.")(
        "enable-tcp, E", po::value<bool>(), "true for enable TCP Engine; otherwise packet won't go into TcpEngine")(
        "counter-flags, C", po::value<uint32_t>(),
        "input the counter combination testing flags,0:all;1:accessiblity KPI;2:Integrity KPI")(
        "logconfig_xml, l", po::value<std::string>(), "select full path name of log config-xml")(
        "show-result", po::value<bool>(), "true: print out the measure result; otherwise not print")(
        "lru-size", po::value<uint32_t>(), "the size of lru cache, default 1M, ")(
        "acked-size", po::value<uint32_t>(), "the size of lru cache, default 200, ")(
        "unacked-size", po::value<uint32_t>(), "the size of lru cache, default 200, ")(
        "lru-threshold", po::value<uint32_t>(), "batch aging size for lru, default 20000, ")(
        "use_cpu_core", po::value<uint32_t>(), "select running on cpu core, default 20, ")(
        "loop_pcap", po::value<uint32_t>(),
        "If 0, looping is indefinite; otherwise, it last number of times and then stop.  , default loop=1 times, ")(
        "time_wait", po::value<uint32_t>(),
        "pcap repaly will wait tcpEngine for process if latter can't keep pace with pcap replay, default is 10ms ")(
        "max_queue", po::value<uint32_t>(), "maximu queue size of passing packets to TcpEngine,d efal is 100000")(
        "engine-speed", po::value<bool>(),
        "true: measure engine thruput, false: not measure engine speed besides of overall thruput, defaul true ")(
        "enable-csv", po::value<bool>(), "true: enable the csv file; otherwise, no csv file output ")(
        "test_napa", po::value<bool>(), "true: just run test function to napa card; otherwise, run harness to TcpEngine");

    po::positional_options_description p;
    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);
    if (vm.count("help") || vm.size() < 1) {
      std::cout << "command options:" << std::endl;
      std::cout << desc;
      return 0;
    }
    if (vm.count("input-pcap")) {
      xtreme::iwf::get_option().arrPcap = vm["input-pcap"].as<std::vector<std::string> >();
    }
    if (vm.count("pcap-path")) {
      xtreme::iwf::get_option().pcapPath = vm["pcap-path"].as<std::string>();
    }
    if (vm.count("enable-tcp")) {
      xtreme::iwf::get_option().enableTcpEngine = vm["enable-tcp"].as<bool>();
    }
    if (vm.count("counter-flags")) {
      xtreme::iwf::get_option().counterFlags = vm["counter-flags"].as<uint32_t>();
    }

    if (vm.count("show-result")) {
      xtreme::iwf::get_option().show_result = vm["show-result"].as<bool>();
    } else {
      xtreme::iwf::get_option().show_result = true;
    }
    if (vm.count("logconfig_xml")) {
      xtreme::iwf::get_option().logconfig_xml = vm["logconfig_xml"].as<std::string>();
    }
    if (vm.count("acked-size")) {
      xtreme::ITcpMeasure::options().retrx_ack_table_size = vm["acked-size"].as<uint32_t>();
    }
    if (vm.count("unacked-size")) {
      xtreme::ITcpMeasure::options().max_unacked = vm["acked-size"].as<uint32_t>();
    }
    if (vm.count("lru-size")) {
      xtreme::ITcpMeasure::options().lru_cache_size = vm["lru-size"].as<uint32_t>();
    }
    if (vm.count("lru-threshold")) {
      xtreme::ITcpMeasure::options().lru_cache_throttle_threshold_ = vm["lru-threshold"].as<uint32_t>();
    }
    log4cxx::xml::DOMConfigurator::configure(xtreme::iwf::get_option().logconfig_xml);
    //log4cxx::BasicConfigurator::configure();
    if (vm.count("enable-csv")) {
      xtreme::ITcpMeasure::options().csv_enable = vm["enable-csv"].as<bool>();
      ITcpMeasure::options().strCSV_Path = "/var/log/mri";
    }

    if (xtreme::iwf::get_option().enableTcpEngine) {
      xtreme::ITcpMeasure::options().enable = true;
      xtreme::ITcpMeasure::options().telemetry = true;
    }
    std::cout << "enable tcp=" << xtreme::ITcpMeasure::options().enable << std::endl;

    if (vm.count("time_wait")) {
      xtreme::iwf::get_option().time_wait = vm["time_wait"].as<uint32_t>();
    }

    if (vm.count("max_queue")) {
      xtreme::iwf::get_option().max_queue = vm["max_queue"].as<uint32_t>();
    }

    if (vm.count("use_cpu_core")) {
      xtreme::iwf::get_option().cpu_core = vm["use_cpu_core"].as<uint32_t>();
    }
    if (vm.count("loop_pcap")) {
      xtreme::iwf::get_option().loop_pcap = vm["loop_pcap"].as<uint32_t>();
    }

    if (vm.count("engine-speed")) {
      xtreme::iwf::get_option().measure_engine = vm["engine-speed"].as<bool>();
      xtreme::ITcpMeasure::options().engine_speed = vm["engine-speed"].as<bool>();
    } else {
      xtreme::iwf::get_option().measure_engine = true;
      xtreme::ITcpMeasure::options().engine_speed = true;
    }

    if (vm.count("streams")) {
      xtreme::iwf::get_option().streams = vm["streams"].as<uint32_t>();
    } else {
      xtreme::iwf::get_option().streams = 16;
    }
    if (vm.count("upp_streams")) {
      xtreme::iwf::get_option().upp_streams = vm["upp_streams"].as<uint32_t>();
    } else {
      xtreme::iwf::get_option().upp_streams = 15;
    }
    if (vm.count("core_per_cpu")) {
      xtreme::iwf::get_option().core_per_cpu = vm["core_per_cpu"].as<uint32_t>();
    } else {
      xtreme::iwf::get_option().core_per_cpu = 1;
    }
    if (vm.count("test_napa")) {
      xtreme::iwf::get_option().napa_test = vm["test_napa"].as<bool>();
    } else {
      xtreme::iwf::get_option().napa_test = false;
    }
    if (vm.count("zero_copy")) {
      xtreme::iwf::get_option().zero_copy = vm["zero_copy"].as<bool>();
    } else {
      xtreme::iwf::get_option().zero_copy = false;
    }
    //ensure test harness tool will not let tcpengine to do the speed measure.
    xtreme::ITcpMeasure::options().engine_speed = false;
    std::cout << "[engine_speed]-----------:" << (xtreme::iwf::get_option().measure_engine ? "on" : "off") << std::endl;
    std::cout << "[telementry]-------------:" << (xtreme::ITcpMeasure::options().telemetry ? "on" : "off") << std::endl;
    std::cout << "[max_queue]--------------:" << xtreme::iwf::get_option().max_queue << std::endl;
    std::cout << "[time_wait]--------------:" << xtreme::iwf::get_option().time_wait << " ms" << std::endl;
    std::cout << "[loop pcap]--------------:" << xtreme::iwf::get_option().loop_pcap << std::endl;
    std::cout << "[streams]----------------:" << xtreme::iwf::get_option().streams << std::endl;
    std::cout << "[upp_streams]------------:" << xtreme::iwf::get_option().upp_streams << std::endl;
    std::cout << "[core_per_cpu]-----------:" << xtreme::iwf::get_option().core_per_cpu << std::endl;
    std::cout << "[test_napa]--------------:" << (xtreme::iwf::get_option().napa_test ? "yes" : "no") << std::endl;
    std::cout << "[zero_copy]--------------:" << (xtreme::iwf::get_option().zero_copy ? "yes" : "no") << std::endl;
  } catch (...) {
    return -1;
  }
  return 0;
}

static int g_interrupt_count = 0;
int get_interrupt_count() {
  return g_interrupt_count;
}

void signal_handler(int /* sig */) {
  ++g_interrupt_count;
  TCP_MSG_INFO("signal_handler: g_interrupt_count=%d", g_interrupt_count);
}
