#include "lxcstat.h"

#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

#include "parsing.h"

int parseLxcConfigFile(lxcinfo *lxc, char *filedata) {
  char *temp = filedata;
  lxc->cpucount = findAndParseField(&temp, "cores");
  temp = filedata;

  lxc->memlimit = findAndParseField(&temp, "memory") * 1024 * 1024;
  temp = filedata;

  lxc->swaplimit = findAndParseField(&temp, "swap") * 1024 * 1024;

  char *ptr = strstr(filedata, "hostname:");
  ptr += strlen("hostname:");
  while (*ptr == ' ') ptr++;
  strtok(ptr, "\n\t ");
  strcpy(lxc->hostname, ptr);
}

int readLxcConfig(lxcinfo *lxc, int lxcid) {
  char *fname = malloc(1024);
  char *buffer = malloc(4096);

  sprintf(fname, "/etc/pve/lxc/%d.conf", lxcid);
  FILE *file = fopen(fname, "rb");
  if (file == NULL) {
    printf("Failed to open <%s>: %d\n", fname, errno);
    return -1;
  }
  fread(buffer, 1, 4096, file);
  fclose(file);

  parseLxcConfigFile(lxc, buffer);
  free(buffer);
  free(fname);
  return 0;
}

void getInactiveLXCs(lxcinfo **lxcs) {
  struct dirent *pDirent;
  DIR *pDir;

  // Ensure we can open directory.
  pDir = opendir("/etc/pve/lxc");
  if (pDir == NULL) {
    printf("Cannot open directory '/etc/pve/lxc'\n");
    return;
  }

  // Process each entry.
  while ((pDirent = readdir(pDir)) != NULL) {
    char *fname = pDirent->d_name;
    char extension[20];
    int lxcid;

    int argc = sscanf(fname, "%d.%s", &lxcid, (char *) extension);
    // ensure it's an LXC config
    if (argc != 2 || strcmp((char *) extension, "conf") != 0) continue;
    getLXCInfo(lxcs, lxcid);  // don't care about result
  }

  closedir(pDir);
}

lxcinfo *getLXCInfo(lxcinfo **lxcs, int lxcid) {
  lxcinfo *lxc = *lxcs;
  while (lxc != NULL) {
    if (lxc->lxcid == lxcid) return lxc;
    lxc = lxc->next;
  }

  lxc = calloc(1, sizeof(lxcinfo));
  lxc->lxcid = lxcid;
  lxc->running = 0;

  if (readLxcConfig(lxc, lxcid)) {
    // failed to read LXC
    free(lxc);
    return NULL;
  }

  if (*lxcs == NULL) {
    // head was NULL - first LXC
    *lxcs = lxc;
    lxc->head = lxc;
    lxc->tail = lxc;
    lxc->next = NULL;
  } else {
    // other LXCs exist - chain to tail
    (*lxcs)->tail->next = lxc;
    (*lxcs)->tail = lxc;
    lxc->head = *lxcs;
    lxc->next = NULL;
  }

  return lxc;
}
