#include "udsf_config.hpp"

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <arpa/inet.h>



#include <iostream>

#include "logger.hpp"

using namespace libconfig;

namespace config {
udsf_config::udsf_config() {}
udsf_config::~udsf_config() {}

int udsf_config::load(const std ::string &config_file) {
  Logger::udsf_app().debug("\nLoad UDR system configuration file(%s)",
                          config_file.c_str());

  Config cfg;
  try {
    cfg.readFile(config_file.c_str());
  } catch (const FileIOException &fioex) {
    Logger::udsf_app().error("I/O error while reading file %s - %s",
                            config_file.c_str(), fioex.what());
    throw;
  } catch (const ParseException &pex) {
    Logger::udsf_app().error("Parse error at %s:%d - %s", pex.getFile(),
                            pex.getLine(), pex.getError());
    throw;
  }
  const Setting &root = cfg.getRoot();
  try {
    const Setting &udsf_cfg = root[UDSF_CONFIG_STRING_UDSF_CONFIG];
  } catch (const SettingNotFoundException &nfex) {
    Logger::udsf_app().error("%s : %s", nfex.what(), nfex.getPath());
    return -1;
  }
  const Setting &udsf_cfg = root[UDSF_CONFIG_STRING_UDSF_CONFIG];
  try {
    udsf_cfg.lookupValue(UDSF_CONFIG_STRING_INSTANCE_ID, instance);
  } catch (const SettingNotFoundException &nfex) {
    Logger::udsf_app().warn("%s : %s, using defaults", nfex.what(),
                            nfex.getPath());
  }
  try {
    udsf_cfg.lookupValue(UDSF_CONFIG_STRING_PID_DIRECTORY, pid_dir);
  } catch (const SettingNotFoundException &nfex) {
    Logger::udsf_app().warn("%s : %s, using defaults", nfex.what(),
                            nfex.getPath());
  }

  try {
    const Setting &new_if_cfg = udsf_cfg[UDSF_CONFIG_STRING_INTERFACES];
    const Setting &sbi_cfg = new_if_cfg[UDSF_CONFIG_STRING_INTERFACE_SBI];
    load_interface(sbi_cfg, sbi);
  } catch (const SettingNotFoundException &nfex) {
    Logger::udsf_app().error("%s : %s", nfex.what(),
                            nfex.getPath());
    return -1;
  }


  try {
    const Setting &mysql_cfg = udsf_cfg[UDSF_CONFIG_STRING_MYSQL];
    mysql_cfg.lookupValue(UDSF_CONFIG_STRING_MYSQL_SERVER, mysql.mysql_server);
    mysql_cfg.lookupValue(UDSF_CONFIG_STRING_MYSQL_USER, mysql.mysql_user);
    mysql_cfg.lookupValue(UDSF_CONFIG_STRING_MYSQL_PASS, mysql.mysql_pass);
    mysql_cfg.lookupValue(UDSF_CONFIG_STRING_MYSQL_DB, mysql.mysql_db);
    mysql_cfg.lookupValue(UDSF_CONFIG_STRING_MYSQL_PORT, mysql.mysql_port);
  } catch (const SettingNotFoundException &nfex) {
    Logger::udsf_app().error("%s : %s", nfex.what(),
                            nfex.getPath());
    return -1;
  }

  return 0;
}
int udsf_config::load_interface(const libconfig::Setting &if_cfg,
                               interface_cfg_t &cfg) {
  if_cfg.lookupValue(UDSF_CONFIG_STRING_INTERFACE_NAME, cfg.if_name);
  if_cfg.lookupValue(UDSF_CONFIG_STRING_IPV4_ADDRESS, cfg.addr4);
  if(!cfg.addr4.compare("read"))
  {
    if(getip(cfg.addr4,cfg.if_name) < 0) return -1;
  }
  if_cfg.lookupValue(UDSF_CONFIG_STRING_PORT, cfg.port);

  return 0;
}
int udsf_config::getip(std::string &ip, std::string &ifname)
{
    int sock;
    struct sockaddr_in sin;
    struct ifreq ifr;
    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock == -1)
    {
        perror("socket");
        return -1;
    }
    strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ);
    ifr.ifr_name[IFNAMSIZ - 1] = 0;
    if (ioctl(sock, SIOCGIFADDR, &ifr) < 0)
    {
        perror("ioctl");
        return -1;
    }
    memcpy(&sin, &ifr.ifr_addr, sizeof(sin));
    printf("ip = %s",inet_ntoa(sin.sin_addr));
    //sprintf(ip, "%s", inet_ntoa(sin.sin_addr));
    ip = std::string(inet_ntoa(sin.sin_addr));
    return 0;
}
void udsf_config::display() {
  Logger::config().info(
      "======================    UDSF   =====================");
  Logger::config().info("Configuration UDSF:");
  Logger::config().info("");
  Logger::config().info(
      "- Instance .........................................: %d", instance);
  Logger::config().info(
      "- PID dir ..........................................: %s",
      pid_dir.c_str());
  Logger::config().info("");

  Logger::config().info("- SBI Networking:");
  Logger::config().info("    iface ................: %s", sbi.if_name.c_str());
  Logger::config().info("    ip ...................: %s", sbi.addr4.c_str());
  Logger::config().info("    port .................: %d", sbi.port);
  Logger::config().info("");

  Logger::config().info("- Database Configuration:");
  Logger::config().info(
      "- MYSQL Server Addr.................................: %s",
      mysql.mysql_server.c_str());
  Logger::config().info(
      "- MYSQL User .......................................: %s",
      mysql.mysql_user.c_str());
  Logger::config().info(
      "- MYSQL Pass .......................................: %s",
      mysql.mysql_pass.c_str());
  Logger::config().info(
      "- MYSQL DB .........................................: %s",
      mysql.mysql_db.c_str());
  Logger::config().info(
      "- MYSQL Port .......................................: %d",
      mysql.mysql_port);
  Logger::config().info("");


}
} // namespace config
