#include "aos/configuration.h"

#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <unistd.h>

#include "aos/logging/logging.h"
#include "aos/unique_malloc_ptr.h"
#include "aos/once.h"

namespace aos {
namespace configuration {
namespace {

// TODO(brians): This shouldn't be necesary for running tests.  Provide a way to
// set the IP address when running tests from the test.
const char *const kLinuxNetInterface = "eth0";
const in_addr *DoGetOwnIPAddress() {
  static const char *kOverrideVariable = "FRC971_IP_OVERRIDE";
  const char *override_ip = getenv(kOverrideVariable);
  if (override_ip != NULL) {
    LOG(INFO, "Override IP is %s\n", override_ip);
    static in_addr r;
    if (inet_aton(override_ip, &r) != 0) {
      return &r;
    } else {
      LOG(WARNING, "error parsing %s value '%s'\n",
          kOverrideVariable, override_ip);
    }
  } else {
    LOG(INFO, "Couldn't get environmental variable.\n");
  }

  ifaddrs *addrs;
  if (getifaddrs(&addrs) != 0) {
    PLOG(FATAL, "getifaddrs(%p) failed", &addrs);
  }
  // Smart pointers don't work very well for iterating through a linked list,
  // but it does do a very nice job of making sure that addrs gets freed.
  unique_c_ptr<ifaddrs, freeifaddrs> addrs_deleter(addrs);

  for (; addrs != nullptr; addrs = addrs->ifa_next) {
    // ifa_addr tends to be nullptr on CAN interfaces.
    if (addrs->ifa_addr != nullptr && addrs->ifa_addr->sa_family == AF_INET) {
      if (strcmp(kLinuxNetInterface, addrs->ifa_name) == 0) {
        static const in_addr r =
            reinterpret_cast<sockaddr_in *>(__builtin_assume_aligned(
                addrs->ifa_addr, alignof(sockaddr_in)))->sin_addr;
        return &r;
      }
    }
  }
  LOG(FATAL, "couldn't find an AF_INET interface named \"%s\"\n",
      kLinuxNetInterface);
}

const char *DoGetRootDirectory() {
  ssize_t size = 0;
  char *r = NULL;
  while (true) {
    if (r != NULL) delete r;
    size += 256;
    r = new char[size];

    ssize_t ret = readlink("/proc/self/exe", r, size);
    if (ret < 0) {
      if (ret != -1) {
        LOG(WARNING, "it returned %zd, not -1\n", ret);
      }
      PLOG(FATAL, "readlink(\"/proc/self/exe\", %p, %zu) failed", r, size);
    }
    if (ret < size) {
      void *last_slash = memrchr(r, '/', ret);
      if (last_slash == NULL) {
        r[ret] = '\0';
        LOG(FATAL, "couldn't find a '/' in \"%s\"\n", r);
      }
      *static_cast<char *>(last_slash) = '\0';
      LOG(INFO, "got a root dir of \"%s\"\n", r);
      return r;
    }
  }
}

const char *DoGetLoggingDirectory() {
  static const char kSuffix[] = "/../../tmp/robot_logs";
  const char *root = GetRootDirectory();
  char *r = new char[strlen(root) + sizeof(kSuffix)];
  strcpy(r, root);
  strcat(r, kSuffix);
  return r;
}

}  // namespace

const char *GetRootDirectory() {
  static aos::Once<const char> once(DoGetRootDirectory);
  return once.Get();
}

const char *GetLoggingDirectory() {
  static aos::Once<const char> once(DoGetLoggingDirectory);
  return once.Get();
}

const in_addr &GetOwnIPAddress() {
  static aos::Once<const in_addr> once(DoGetOwnIPAddress);
  return *once.Get();
}

}  // namespace configuration
}  // namespace aos
