#define FUSE_USE_VERSION 30

#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <fuse3/fuse.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

const int NFILES = 1024;

struct fs_entry {
  int valid;
  char *path;
  char content[4096];
};

struct fs_entry entries[1024];

const char *remove_leading_slash(const char *path) {
  if (path[0] == '/') {
    return &path[1];
  } else {
    return path;
  }
}

struct fs_entry *find_free_entry() {
  for (int i = 0; i < NFILES; i++) {
    if (!entries[i].valid) {
      return &entries[i];
    }
  }
  return NULL;
}

struct fs_entry *find_entry(const char *path) {
  const char *p = remove_leading_slash(path);
  for (int i = 0; i < NFILES; i++) {
    if (entries[i].valid && (strcmp(entries[i].path, p) == 0)) {
      return &entries[i];
    }
  }
  return NULL;
}

static int do_getattr(const char *path, struct stat *st, struct fuse_file_info *fi) {
  printf("[BS2FS] Called getattr (path = %s)\n", path);

  st->st_uid = getuid();
  st->st_gid = getgid();
  clock_gettime(CLOCK_REALTIME, &st->st_atim);
  clock_gettime(CLOCK_REALTIME, &st->st_mtim);

  if (strcmp(path, "/") == 0) {
    st->st_mode = S_IFDIR | 0755;
    st->st_nlink = 2;
    return 0;
  } else if (strcmp(path, "/bs2.txt") == 0) {
    st->st_mode = S_IFREG | 0644;
    st->st_nlink = 1;
    st->st_size = 4096;
    return 0;
  } else {
    return -ENOENT;
  }
  return 0;
}

static int do_readdir(const char *path, void *buffer, fuse_fill_dir_t fill, off_t offset, struct fuse_file_info *fi, enum fuse_readdir_flags flags) {
  fill(buffer, ".", NULL, 0, 0);
  fill(buffer, "..", NULL, 0, 0);

  fill(buffer, "bs2.txt", NULL, 0, 0);
  return 0;
}

static int do_read(const char *path, char *buffer, size_t size, off_t off, struct fuse_file_info *fi)  {
  const char *file_content = "Hello, BS2!";
  if (strcmp(path, "/bs2.txt") == 0) {
    memcpy(buffer, file_content + off, size);
    return strlen(file_content) - off;
  }
  return 0;
}

struct fuse_operations operations =  {
  .getattr = do_getattr,
  .readdir = do_readdir,
  .read = do_read,
};

int main(int argc, char* argv[]) {
  return fuse_main(argc, argv, &operations, NULL);
}
