#include "FuseBinding.hpp"

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>

namespace DC { namespace Fuse
{
  /* Port of FUSE example hello.c - Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu> */

  class HelloFS
  {
    public:

      static int hello_getattr(const char *path, struct stat *stbuf)
      {
        int res = 0;

        memset(stbuf, 0, sizeof(struct stat));
        if(strcmp(path, "/") == 0) {
          stbuf->st_mode = S_IFDIR | 0755;
          stbuf->st_nlink = 2;
        }
        else if(strcmp(path, hello_path) == 0) {
          stbuf->st_mode = S_IFREG | 0444;
          stbuf->st_nlink = 1;
          stbuf->st_size = strlen(hello_str);
        }
        else
          res = -ENOENT;

        return res;
      }

      static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi)
      {
        (void) offset;
        (void) fi;

        if(strcmp(path, "/") != 0)
          return -ENOENT;

        filler(buf, ".", NULL, 0);
        filler(buf, "..", NULL, 0);
        filler(buf, hello_path + 1, NULL, 0);

        return 0;
      }

      static int hello_open(const char *path, struct fuse_file_info *fi)
      {
        if(strcmp(path, hello_path) != 0)
          return -ENOENT;

        if((fi->flags & 3) != O_RDONLY)
          return -EACCES;

        return 0;
      }

      static int hello_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi)
      {
        size_t len;
        (void) fi;
        if(strcmp(path, hello_path) != 0)
          return -ENOENT;

        len = strlen(hello_str);
        if (offset < len) {
          if (offset + size > len)
            size = len - offset;
          memcpy(buf, hello_str + offset, size);
        } else
          size = 0;

        return size;
      }

    private:
      static const char* hello_str;
      static const char* hello_path;
  };

  const char* HelloFS::hello_str = "Hello world!\n";
  const char* HelloFS::hello_path = "/hello";

}}

using namespace DC::Fuse;

int main(int argc, char *argv[])
{
    FuseBinding binding;
    binding.set_getattr (HelloFS::hello_getattr);
    binding.set_read    (HelloFS::hello_read);
    binding.set_open    (HelloFS::hello_open);
    binding.set_readdir (HelloFS::hello_readdir);

    return fuse_main(argc, argv, binding.get_operations(), NULL);
}

