#include <stddef.h>
#include <stdint.h>
#include <ulib.h>

struct {
  bool plain;
  bool names;
  bool sizes;
  bool types;
  bool humsz;
} FS_FETCH_CONFIG = {
  .plain = false,
  .names = true,
  .sizes = true,
  .types = true,
  .humsz = true,
};

static Arg ARGS[] = {
  ARG("-p", ARG_BOOL, &FS_FETCH_CONFIG.plain),
  ARG("-n", ARG_BOOL, &FS_FETCH_CONFIG.names),
  ARG("-s", ARG_BOOL, &FS_FETCH_CONFIG.sizes),
  ARG("-t", ARG_BOOL, &FS_FETCH_CONFIG.types),
  ARG("-h", ARG_BOOL, &FS_FETCH_CONFIG.humsz),
  ARG_END(),
};

void fs_fetch(void) {
  if (argslen() < 2) {
    uprintf("fs: Not enough arguments\n");
    return;
  }

  char *path = *(args()+1);

  int32_t ret;
  if ((ret = parse_args(args()+2, argslen()-2, ARGS)) < 0) {
    uprintf("fs: could not parse args: %d\n", ret);
    return;
  }

  if (FS_FETCH_CONFIG.plain) {
    FS_FETCH_CONFIG.sizes = false;
    FS_FETCH_CONFIG.types = false;
  }

  FsStat statbuf; ZERO(&statbuf);
  if (fs_stat(path, &statbuf) != E_OK) {
    uprintf("fs: could not stat %s\n", path);
    return;
  }

  if (statbuf.type == FSSTAT_FILE) {
    fsh_t h = fs_openf(path, FS_OF_READ);
    if (h < 0) {
      uprintf("fs: could not open %s\n", path);
      return;
    }

    uint8_t *buf = umalloc(statbuf.size+1);
    string_memset(buf, 0, statbuf.size+1);

    if (fs_read(h, buf, statbuf.size, 0)) {
      uprintf("fs: coult not read %s\n", path);
      goto donefile;
      return;
    }

    uprintf("%s", buf);
  donefile:
    ufree(buf);
    fs_closef(h);
  } else if (statbuf.type == FSSTAT_DIR) {
    FsDirent *dirents = (FsDirent *)umalloc(statbuf.size * sizeof(*dirents));

    for (size_t i = 0; i < statbuf.size; i++) {
      fs_fetchdirent(path, &dirents[i], i);

      FsDirent *dirent = &dirents[i];
        
      if (FS_FETCH_CONFIG.names) {
        if (FS_FETCH_CONFIG.plain) {
          uprintf("%s ", dirent->name);
        } else {
          uprintf("%-30s ", dirent->name);
        }
      }

      if  (FS_FETCH_CONFIG.sizes) {
        if (dirent->stat.type == FSSTAT_FILE) {
          if (FS_FETCH_CONFIG.humsz) {
            char *membuf = umalloc(20);
          
            if (FS_FETCH_CONFIG.plain) {
              uprintf("%s ", human_size(dirent->stat.size, membuf, 20));
            } else {
              uprintf("%-15s ", human_size(dirent->stat.size, membuf, 20));
            }

            ufree(membuf);
          } else {
            if (FS_FETCH_CONFIG.plain) {
              uprintf("%zu ", dirent->stat.size);
            } else {
              uprintf("%-15zu ", dirent->stat.size);
            }
          }
        } else if (dirent->stat.type == FSSTAT_DIR) {
          if (FS_FETCH_CONFIG.plain) {
            uprintf("- ");
          } else {
            uprintf("%-15c ", '-');
          }
        }
      }

      if (FS_FETCH_CONFIG.types) {
        if (dirent->stat.type == FSSTAT_FILE) {
            uprintf("%c ", 'F');
        } else if (dirent->stat.type == FSSTAT_DIR) {
            uprintf("%c ", 'D');
        }
      }

      uprintf("\n");
    }

    ufree(dirents);
  }
}
