/*
 * Copyright © 2019 Google, LLC
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "os_dirent.h"

#include "list.h"
#include "os/fuchsia.h"

#include <limits.h>
#include <string.h>

#include <lib/zxio/zxio.h>

// Offsets must match struct os_dirent, static_asserts below.
struct os_dirent_impl {
   ino_t d_ino;
   char d_name[NAME_MAX + 1];
};

static_assert(offsetof(struct os_dirent_impl, d_ino) == offsetof(struct os_dirent, d_ino),
              "d_ino offset mismatch");
static_assert(offsetof(struct os_dirent_impl, d_name) == offsetof(struct os_dirent, d_name),
              "d_ino offset mismatch");

class os_dir {
public:
   os_dir() {}

   ~os_dir()
   {
      if (dir_iterator_init) {
         zxio_dirent_iterator_destroy(&iterator);
      }
      if (zxio_init) {
         zxio_close(&io_storage.io, /*should_wait=*/true);
      }
   }

   // Always consumes |dir_channel|
   bool Init(zx_handle_t dir_channel)
   {
      zx_status_t status = zxio_create(dir_channel, &io_storage);
      if (status != ZX_OK) {
         FUCHSIA_DLOG("zxio_create failed: %d", status);
         return false;
      }

      zxio_init = true;

      status = zxio_dirent_iterator_init(&iterator, &io_storage.io);
      if (status != ZX_OK) {
         FUCHSIA_DLOG("zxio_dirent_iterator_init failed: %d", status);
         return false;
      }
      dir_iterator_init = true;

      return true;
   }

   struct os_dirent_impl* Next()
   {
      zxio_dirent_t dirent = {.name = entry.d_name};
      zx_status_t status = zxio_dirent_iterator_next(&iterator, &dirent);
      if (status != ZX_OK) {
         if (status != ZX_ERR_NOT_FOUND)
            FUCHSIA_DLOG("zxio_dirent_iterator_next failed: %d", status);
         return nullptr;
      }

      entry.d_ino = dirent.has.id ? dirent.id : OS_INO_UNKNOWN;
      entry.d_name[dirent.name_length] = '\0';

      return &entry;
   }

private:
   bool zxio_init = false;
   bool dir_iterator_init = false;
   zxio_storage_t io_storage;
   zxio_dirent_iterator_t iterator;
   struct os_dirent_impl entry;
};

os_dir_t* os_opendir(const char* path)
{
   zx_handle_t dir_channel;
   if (!fuchsia_open(path, &dir_channel)) {
      FUCHSIA_DLOG("fuchsia_open(%s) failed\n", path);
      return nullptr;
   }

   auto dir = new os_dir();

   if (!dir->Init(dir_channel)) {
      delete dir;
      return nullptr;
   }

   return dir;
}

int os_closedir(os_dir_t* dir)
{
   // Assume param is valid.
   delete dir;
   return 0;
}

struct os_dirent* os_readdir(os_dir_t* dir) { return reinterpret_cast<os_dirent*>(dir->Next()); }
