#include "node_dir.h"
#include "node_external_reference.h"
#include "node_file-inl.h"
#include "node_process-inl.h"
#include "memory_tracker-inl.h"
#include "util.h"

#include "tracing/trace_event.h"

#include "string_bytes.h"

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <cstring>
#include <cerrno>
#include <climits>

#include <memory>

namespace node {

namespace fs_dir {

using fs::FSReqAfterScope;
using fs::FSReqBase;
using fs::FSReqWrapSync;
using fs::GetReqWrap;

using v8::Array;
using v8::Context;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::HandleScope;
using v8::Integer;
using v8::Isolate;
using v8::Local;
using v8::MaybeLocal;
using v8::Null;
using v8::Number;
using v8::Object;
using v8::ObjectTemplate;
using v8::Value;

#define TRACE_NAME(name) "fs_dir.sync." #name
#define GET_TRACE_ENABLED                                                      \
  (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED                                 \
  (TRACING_CATEGORY_NODE2(fs_dir, sync)) != 0)
#define FS_DIR_SYNC_TRACE_BEGIN(syscall, ...)                                  \
  if (GET_TRACE_ENABLED)                                                       \
  TRACE_EVENT_BEGIN(TRACING_CATEGORY_NODE2(fs_dir, sync), TRACE_NAME(syscall), \
  ##__VA_ARGS__);
#define FS_DIR_SYNC_TRACE_END(syscall, ...)                                    \
  if (GET_TRACE_ENABLED)                                                       \
  TRACE_EVENT_END(TRACING_CATEGORY_NODE2(fs_dir, sync), TRACE_NAME(syscall),   \
  ##__VA_ARGS__);

DirHandle::DirHandle(Environment* env, Local<Object> obj, uv_dir_t* dir)
    : AsyncWrap(env, obj, AsyncWrap::PROVIDER_DIRHANDLE),
      dir_(dir) {
  MakeWeak();

  dir_->nentries = 0;
  dir_->dirents = nullptr;
}

DirHandle* DirHandle::New(Environment* env, uv_dir_t* dir) {
  Local<Object> obj;
  if (!env->dir_instance_template()
          ->NewInstance(env->context())
          .ToLocal(&obj)) {
    return nullptr;
  }

  return new DirHandle(env, obj, dir);
}

void DirHandle::New(const FunctionCallbackInfo<Value>& args) {
  CHECK(args.IsConstructCall());
}

DirHandle::~DirHandle() {
  CHECK(!closing_);  // We should not be deleting while explicitly closing!
  GCClose();         // Close synchronously and emit warning
  CHECK(closed_);    // We have to be closed at the point
}

void DirHandle::MemoryInfo(MemoryTracker* tracker) const {
  tracker->TrackFieldWithSize("dir", sizeof(*dir_));
}

// Close the directory handle if it hasn't already been closed. A process
// warning will be emitted using a SetImmediate to avoid calling back to
// JS during GC. If closing the fd fails at this point, a fatal exception
// will crash the process immediately.
inline void DirHandle::GCClose() {
  if (closed_) return;
  uv_fs_t req;
  int ret = uv_fs_closedir(nullptr, &req, dir_, nullptr);
  uv_fs_req_cleanup(&req);
  closing_ = false;
  closed_ = true;

  struct err_detail { int ret; };

  err_detail detail { ret };

  if (ret < 0) {
    // Do not unref this
    env()->SetImmediate([detail](Environment* env) {
      const char* msg = "Closing directory handle on garbage collection failed";
      // This exception will end up being fatal for the process because
      // it is being thrown from within the SetImmediate handler and
      // there is no JS stack to bubble it to. In other words, tearing
      // down the process is the only reasonable thing we can do here.
      HandleScope handle_scope(env->isolate());
      env->ThrowUVException(detail.ret, "close", msg);
    });
    return;
  }

  // If the close was successful, we still want to emit a process warning
  // to notify that the file descriptor was gc'd. We want to be noisy about
  // this because not explicitly closing the DirHandle is a bug.

  env()->SetImmediate([](Environment* env) {
    ProcessEmitWarning(env,
                       "Closing directory handle on garbage collection");
  }, CallbackFlags::kUnrefed);
}

void AfterClose(uv_fs_t* req) {
  FSReqBase* req_wrap = FSReqBase::from_req(req);
  FSReqAfterScope after(req_wrap, req);

  if (after.Proceed())
    req_wrap->Resolve(Undefined(req_wrap->env()->isolate()));
}

void DirHandle::Close(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);

  const int argc = args.Length();
  CHECK_GE(argc, 1);

  DirHandle* dir;
  ASSIGN_OR_RETURN_UNWRAP(&dir, args.Holder());

  dir->closing_ = false;
  dir->closed_ = true;

  FSReqBase* req_wrap_async = GetReqWrap(args, 0);
  if (req_wrap_async != nullptr) {  // close(req)
    AsyncCall(env, req_wrap_async, args, "closedir", UTF8, AfterClose,
              uv_fs_closedir, dir->dir());
  } else {  // close(undefined, ctx)
    CHECK_EQ(argc, 2);
    FSReqWrapSync req_wrap_sync;
    FS_DIR_SYNC_TRACE_BEGIN(closedir);
    SyncCall(env, args[1], &req_wrap_sync, "closedir", uv_fs_closedir,
             dir->dir());
    FS_DIR_SYNC_TRACE_END(closedir);
  }
}

static MaybeLocal<Array> DirentListToArray(
    Environment* env,
    uv_dirent_t* ents,
    int num,
    enum encoding encoding,
    Local<Value>* err_out) {
  MaybeStackBuffer<Local<Value>, 64> entries(num * 2);

  // Return an array of all read filenames.
  int j = 0;
  for (int i = 0; i < num; i++) {
    Local<Value> filename;
    Local<Value> error;
    const size_t namelen = strlen(ents[i].name);
    if (!StringBytes::Encode(env->isolate(),
                             ents[i].name,
                             namelen,
                             encoding,
                             &error).ToLocal(&filename)) {
      *err_out = error;
      return MaybeLocal<Array>();
    }

    entries[j++] = filename;
    entries[j++] = Integer::New(env->isolate(), ents[i].type);
  }

  return Array::New(env->isolate(), entries.out(), j);
}

static void AfterDirRead(uv_fs_t* req) {
  BaseObjectPtr<FSReqBase> req_wrap { FSReqBase::from_req(req) };
  FSReqAfterScope after(req_wrap.get(), req);

  if (!after.Proceed()) {
    return;
  }

  Environment* env = req_wrap->env();
  Isolate* isolate = env->isolate();

  if (req->result == 0) {
    // Done
    Local<Value> done = Null(isolate);
    after.Clear();
    req_wrap->Resolve(done);
    return;
  }

  uv_dir_t* dir = static_cast<uv_dir_t*>(req->ptr);

  Local<Value> error;
  Local<Array> js_array;
  if (!DirentListToArray(env,
                         dir->dirents,
                         static_cast<int>(req->result),
                         req_wrap->encoding(),
                         &error)
           .ToLocal(&js_array)) {
    // Clear libuv resources *before* delivering results to JS land because
    // that can schedule another operation on the same uv_dir_t. Ditto below.
    after.Clear();
    return req_wrap->Reject(error);
  }

  after.Clear();
  req_wrap->Resolve(js_array);
}


void DirHandle::Read(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  Isolate* isolate = env->isolate();

  const int argc = args.Length();
  CHECK_GE(argc, 3);

  const enum encoding encoding = ParseEncoding(isolate, args[0], UTF8);

  DirHandle* dir;
  ASSIGN_OR_RETURN_UNWRAP(&dir, args.Holder());

  CHECK(args[1]->IsNumber());
  uint64_t buffer_size = static_cast<uint64_t>(args[1].As<Number>()->Value());

  if (buffer_size != dir->dirents_.size()) {
    dir->dirents_.resize(buffer_size);
    dir->dir_->nentries = buffer_size;
    dir->dir_->dirents = dir->dirents_.data();
  }

  FSReqBase* req_wrap_async = GetReqWrap(args, 2);
  if (req_wrap_async != nullptr) {  // dir.read(encoding, bufferSize, req)
    AsyncCall(env, req_wrap_async, args, "readdir", encoding,
              AfterDirRead, uv_fs_readdir, dir->dir());
  } else {  // dir.read(encoding, bufferSize, undefined, ctx)
    CHECK_EQ(argc, 4);
    FSReqWrapSync req_wrap_sync;
    FS_DIR_SYNC_TRACE_BEGIN(readdir);
    int err = SyncCall(env, args[3], &req_wrap_sync, "readdir", uv_fs_readdir,
                       dir->dir());
    FS_DIR_SYNC_TRACE_END(readdir);
    if (err < 0) {
      return;  // syscall failed, no need to continue, error info is in ctx
    }

    if (req_wrap_sync.req.result == 0) {
      // Done
      Local<Value> done = Null(isolate);
      args.GetReturnValue().Set(done);
      return;
    }

    CHECK_GE(req_wrap_sync.req.result, 0);

    Local<Value> error;
    Local<Array> js_array;
    if (!DirentListToArray(env,
                           dir->dir()->dirents,
                           static_cast<int>(req_wrap_sync.req.result),
                           encoding,
                           &error)
             .ToLocal(&js_array)) {
      Local<Object> ctx = args[2].As<Object>();
      USE(ctx->Set(env->context(), env->error_string(), error));
      return;
    }

    args.GetReturnValue().Set(js_array);
  }
}

void AfterOpenDir(uv_fs_t* req) {
  FSReqBase* req_wrap = FSReqBase::from_req(req);
  FSReqAfterScope after(req_wrap, req);

  if (!after.Proceed()) {
    return;
  }

  Environment* env = req_wrap->env();

  uv_dir_t* dir = static_cast<uv_dir_t*>(req->ptr);
  DirHandle* handle = DirHandle::New(env, dir);

  req_wrap->Resolve(handle->object().As<Value>());
}

static void OpenDir(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  Isolate* isolate = env->isolate();

  const int argc = args.Length();
  CHECK_GE(argc, 3);

  BufferValue path(isolate, args[0]);
  CHECK_NOT_NULL(*path);

  const enum encoding encoding = ParseEncoding(isolate, args[1], UTF8);

  FSReqBase* req_wrap_async = GetReqWrap(args, 2);
  if (req_wrap_async != nullptr) {  // openDir(path, encoding, req)
    AsyncCall(env, req_wrap_async, args, "opendir", encoding, AfterOpenDir,
              uv_fs_opendir, *path);
  } else {  // openDir(path, encoding, undefined, ctx)
    CHECK_EQ(argc, 4);
    FSReqWrapSync req_wrap_sync;
    FS_DIR_SYNC_TRACE_BEGIN(opendir);
    int result = SyncCall(env, args[3], &req_wrap_sync, "opendir",
                          uv_fs_opendir, *path);
    FS_DIR_SYNC_TRACE_END(opendir);
    if (result < 0) {
      return;  // syscall failed, no need to continue, error info is in ctx
    }

    uv_fs_t* req = &req_wrap_sync.req;
    uv_dir_t* dir = static_cast<uv_dir_t*>(req->ptr);
    DirHandle* handle = DirHandle::New(env, dir);

    args.GetReturnValue().Set(handle->object().As<Value>());
  }
}

void Initialize(Local<Object> target,
                Local<Value> unused,
                Local<Context> context,
                void* priv) {
  Environment* env = Environment::GetCurrent(context);
  Isolate* isolate = env->isolate();

  SetMethod(context, target, "opendir", OpenDir);

  // Create FunctionTemplate for DirHandle
  Local<FunctionTemplate> dir = NewFunctionTemplate(isolate, DirHandle::New);
  dir->Inherit(AsyncWrap::GetConstructorTemplate(env));
  SetProtoMethod(isolate, dir, "read", DirHandle::Read);
  SetProtoMethod(isolate, dir, "close", DirHandle::Close);
  Local<ObjectTemplate> dirt = dir->InstanceTemplate();
  dirt->SetInternalFieldCount(DirHandle::kInternalFieldCount);
  SetConstructorFunction(context, target, "DirHandle", dir);
  env->set_dir_instance_template(dirt);
}

void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
  registry->Register(OpenDir);
  registry->Register(DirHandle::New);
  registry->Register(DirHandle::Read);
  registry->Register(DirHandle::Close);
}

}  // namespace fs_dir

}  // end namespace node

NODE_MODULE_CONTEXT_AWARE_INTERNAL(fs_dir, node::fs_dir::Initialize)
NODE_MODULE_EXTERNAL_REFERENCE(fs_dir, node::fs_dir::RegisterExternalReferences)
