// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "dart-pkg/zircon/sdk_ext/system.h"

#include <array>

#include <ddk/device.h>
#include <fcntl.h>
#include <fuchsia/device/manager/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/io.h>
#include <lib/fdio/limits.h>
#include <lib/fdio/namespace.h>
#include <sys/stat.h>
#include <unistd.h>
#include <zircon/process.h>
#include <zircon/processargs.h>

#include "lib/fsl/io/fd.h"
#include "src/lib/files/unique_fd.h"
#include "third_party/tonic/dart_binding_macros.h"
#include "third_party/tonic/dart_class_library.h"

using tonic::ToDart;

namespace zircon {
namespace dart {

namespace {

constexpr char kGetSizeResult[] = "GetSizeResult";
constexpr char kHandlePairResult[] = "HandlePairResult";
constexpr char kHandleResult[] = "HandleResult";
constexpr char kReadResult[] = "ReadResult";
constexpr char kWriteResult[] = "WriteResult";
constexpr char kFromFileResult[] = "FromFileResult";
constexpr char kMapResult[] = "MapResult";

class ByteDataScope {
 public:
  explicit ByteDataScope(Dart_Handle dart_handle) : dart_handle_(dart_handle) {
    Acquire();
  }

  explicit ByteDataScope(size_t size) {
    dart_handle_ = Dart_NewTypedData(Dart_TypedData_kByteData, size);
    FXL_DCHECK(!tonic::LogIfError(dart_handle_));
    Acquire();
    FXL_DCHECK(size == size_);
  }

  ~ByteDataScope() {
    if (is_valid_) {
      Release();
    }
  }

  void* data() const { return data_; }
  size_t size() const { return size_; }
  Dart_Handle dart_handle() const { return dart_handle_; }
  bool is_valid() const { return is_valid_; }

  void Release() {
    FXL_DCHECK(is_valid_);
    Dart_Handle result = Dart_TypedDataReleaseData(dart_handle_);
    tonic::LogIfError(result);
    is_valid_ = false;
    data_ = nullptr;
    size_ = 0;
  }

 private:
  void Acquire() {
    FXL_DCHECK(size_ == 0);
    FXL_DCHECK(data_ == nullptr);
    FXL_DCHECK(!is_valid_);

    Dart_TypedData_Type type;
    intptr_t size;
    Dart_Handle result =
        Dart_TypedDataAcquireData(dart_handle_, &type, &data_, &size);
    is_valid_ =
        !tonic::LogIfError(result) && type == Dart_TypedData_kByteData && data_;
    if (is_valid_) {
      size_ = size;
    } else {
      size_ = 0;
    }
  }

  Dart_Handle dart_handle_;
  bool is_valid_ = false;
  size_t size_ = 0;
  void* data_ = nullptr;
};

Dart_Handle MakeHandleList(const std::vector<zx_handle_t>& in_handles) {
  tonic::DartClassLibrary& class_library =
      tonic::DartState::Current()->class_library();
  Dart_Handle handle_type = class_library.GetClass("zircon", "Handle");
  Dart_Handle list = Dart_NewListOfType(handle_type, in_handles.size());
  if (Dart_IsError(list))
    return list;
  for (size_t i = 0; i < in_handles.size(); i++) {
    Dart_Handle result =
        Dart_ListSetAt(list, i, ToDart(Handle::Create(in_handles[i])));
    if (Dart_IsError(result))
      return result;
  }
  return list;
}

template <class... Args>
Dart_Handle ConstructDartObject(const char* class_name, Args&&... args) {
  tonic::DartClassLibrary& class_library =
      tonic::DartState::Current()->class_library();
  Dart_Handle type =
      Dart_HandleFromPersistent(class_library.GetClass("zircon", class_name));
  FXL_DCHECK(!tonic::LogIfError(type));

  const char* cstr;
  Dart_StringToCString(Dart_ToString(type), &cstr);

  std::array<Dart_Handle, sizeof...(Args)> args_array{
      {std::forward<Args>(args)...}};
  Dart_Handle object =
      Dart_New(type, Dart_EmptyString(), sizeof...(Args), args_array.data());
  FXL_DCHECK(!tonic::LogIfError(object));
  return object;
}

fxl::UniqueFD FdFromPath(std::string path) {
  // Grab the fdio_ns_t* out of the isolate.
  Dart_Handle zircon_lib = Dart_LookupLibrary(ToDart("dart:zircon"));
  FXL_DCHECK(!tonic::LogIfError(zircon_lib));
  Dart_Handle namespace_type =
      Dart_GetType(zircon_lib, ToDart("_Namespace"), 0, nullptr);
  FXL_DCHECK(!tonic::LogIfError(namespace_type));
  Dart_Handle namespace_field =
      Dart_GetField(namespace_type, ToDart("_namespace"));
  FXL_DCHECK(!tonic::LogIfError(namespace_field));
  uint64_t fdio_ns_ptr;
  Dart_Handle result = Dart_IntegerToUint64(namespace_field, &fdio_ns_ptr);
  FXL_DCHECK(!tonic::LogIfError(result));

  // Get a VMO for the file.
  fdio_ns_t* ns = reinterpret_cast<fdio_ns_t*>(fdio_ns_ptr);
  fxl::UniqueFD dirfd(fdio_ns_opendir(ns));
  if (!dirfd.is_valid())
    return fxl::UniqueFD();

  const char* c_path = path.c_str();
  if (path.length() > 0 && c_path[0] == '/')
    c_path = &c_path[1];
  return fxl::UniqueFD(openat(dirfd.get(), c_path, O_RDONLY));
}

}  // namespace

IMPLEMENT_WRAPPERTYPEINFO(zircon, System);

Dart_Handle System::ChannelCreate(uint32_t options) {
  zx_handle_t out0 = 0, out1 = 0;
  zx_status_t status = zx_channel_create(options, &out0, &out1);
  if (status != ZX_OK) {
    return ConstructDartObject(kHandlePairResult, ToDart(status));
  } else {
    return ConstructDartObject(kHandlePairResult, ToDart(status),
                               ToDart(Handle::Create(out0)),
                               ToDart(Handle::Create(out1)));
  }
}

zx_status_t System::Reboot() {
  zx::channel local, remote;
  auto status = zx::channel::create(0, &local, &remote);
  if (status != ZX_OK) {
    return status;
  }

  const std::string service = std::string{"/svc/"} +
      fuchsia::device::manager::Administrator::Name_;
  status = fdio_service_connect(service.c_str(), remote.get());
  if (status != ZX_OK) {
    printf("failed to connect to service %s: %d\n", service.c_str(), status);
    return status;
  }

  zx_status_t call_status;
  fuchsia::device::manager::Administrator_SyncProxy administrator(std::move(local));
  status = administrator.Suspend(DEVICE_SUSPEND_FLAG_REBOOT, &call_status);
  if (status != ZX_OK || call_status != ZX_OK) {
    printf("Call to %s failed: ret: %d  remote: %d\n", service.c_str(), status, call_status);
  }

  return status != ZX_OK ? status : call_status;
}

Dart_Handle System::ChannelFromFile(std::string path) {
  fxl::UniqueFD fd = FdFromPath(path);
  if (!fd.is_valid()) {
    return ConstructDartObject(kHandleResult, ToDart(ZX_ERR_IO));
  }

  // Get channel from fd.
  zx::channel channel = fsl::CloneChannelFromFileDescriptor(fd.get());
  if (!channel) {
    return ConstructDartObject(kHandleResult, ToDart(ZX_ERR_IO));
  }

  return ConstructDartObject(kHandleResult, ToDart(ZX_OK),
                             ToDart(Handle::Create(channel.release())));
}

zx_status_t System::ChannelWrite(fxl::RefPtr<Handle> channel,
                                 const tonic::DartByteData& data,
                                 std::vector<Handle*> handles) {
  if (!channel || !channel->is_valid()) {
    data.Release();
    return ZX_ERR_BAD_HANDLE;
  }

  std::vector<zx_handle_t> zx_handles;
  for (Handle* handle : handles) {
    zx_handles.push_back(handle->handle());
  }

  zx_status_t status = zx_channel_write(channel->handle(), 0, data.data(),
                                        data.length_in_bytes(),
                                        zx_handles.data(), zx_handles.size());
  // Handles are always consumed.
  for (Handle* handle : handles) {
    handle->ReleaseHandle();
  }

  data.Release();
  return status;
}

Dart_Handle System::ChannelQueryAndRead(fxl::RefPtr<Handle> channel) {
  if (!channel || !channel->is_valid()) {
    return ConstructDartObject(kReadResult, ToDart(ZX_ERR_BAD_HANDLE));
  }

  uint32_t actual_bytes = 0;
  uint32_t actual_handles = 0;

  // Query the size of the next message.
  zx_status_t status = zx_channel_read(channel->handle(), 0, nullptr, nullptr,
                                       0, 0, &actual_bytes, &actual_handles);
  if (status != ZX_ERR_BUFFER_TOO_SMALL) {
    // An empty message or an error.
    return ConstructDartObject(kReadResult, ToDart(status));
  }

  // Allocate space for the bytes and handles.
  ByteDataScope bytes(actual_bytes);
  FXL_DCHECK(bytes.is_valid());
  std::vector<zx_handle_t> handles(actual_handles);

  // Make the call to actually get the message.
  status = zx_channel_read(channel->handle(), 0, bytes.data(), handles.data(),
                           bytes.size(), handles.size(), &actual_bytes,
                           &actual_handles);
  FXL_DCHECK(status != ZX_OK || bytes.size() == actual_bytes);

  bytes.Release();

  if (status == ZX_OK) {
    FXL_DCHECK(handles.size() == actual_handles);

    // return a ReadResult object.
    return ConstructDartObject(kReadResult, ToDart(status), bytes.dart_handle(),
                               ToDart(actual_bytes), MakeHandleList(handles));
  } else {
    return ConstructDartObject(kReadResult, ToDart(status));
  }
}

Dart_Handle System::EventpairCreate(uint32_t options) {
  zx_handle_t out0 = 0, out1 = 0;
  zx_status_t status = zx_eventpair_create(0, &out0, &out1);
  if (status != ZX_OK) {
    return ConstructDartObject(kHandlePairResult, ToDart(status));
  } else {
    return ConstructDartObject(kHandlePairResult, ToDart(status),
                               ToDart(Handle::Create(out0)),
                               ToDart(Handle::Create(out1)));
  }
}

Dart_Handle System::SocketCreate(uint32_t options) {
  zx_handle_t out0 = 0, out1 = 0;
  zx_status_t status = zx_socket_create(options, &out0, &out1);
  if (status != ZX_OK) {
    return ConstructDartObject(kHandlePairResult, ToDart(status));
  } else {
    return ConstructDartObject(kHandlePairResult, ToDart(status),
                               ToDart(Handle::Create(out0)),
                               ToDart(Handle::Create(out1)));
  }
}

Dart_Handle System::SocketWrite(fxl::RefPtr<Handle> socket,
                                const tonic::DartByteData& data,
                                int options) {
  if (!socket || !socket->is_valid()) {
    data.Release();
    return ConstructDartObject(kWriteResult, ToDart(ZX_ERR_BAD_HANDLE));
  }

  size_t actual;
  zx_status_t status = zx_socket_write(socket->handle(), options, data.data(),
                                       data.length_in_bytes(), &actual);
  data.Release();
  return ConstructDartObject(kWriteResult, ToDart(status), ToDart(actual));
}

Dart_Handle System::SocketRead(fxl::RefPtr<Handle> socket, size_t size) {
  if (!socket || !socket->is_valid()) {
    return ConstructDartObject(kReadResult, ToDart(ZX_ERR_BAD_HANDLE));
  }

  ByteDataScope bytes(size);
  size_t actual;
  zx_status_t status =
      zx_socket_read(socket->handle(), 0, bytes.data(), size, &actual);
  bytes.Release();
  if (status == ZX_OK) {
    FXL_DCHECK(actual <= size);
    return ConstructDartObject(kReadResult, ToDart(status), bytes.dart_handle(),
                               ToDart(actual));
  }

  return ConstructDartObject(kReadResult, ToDart(status));
}

Dart_Handle System::VmoCreate(uint64_t size, uint32_t options) {
  zx_handle_t vmo = ZX_HANDLE_INVALID;
  zx_status_t status = zx_vmo_create(size, options, &vmo);
  if (status != ZX_OK) {
    return ConstructDartObject(kHandleResult, ToDart(status));
  } else {
    return ConstructDartObject(kHandleResult, ToDart(status),
                               ToDart(Handle::Create(vmo)));
  }
}

Dart_Handle System::VmoFromFile(std::string path) {
  fxl::UniqueFD fd = FdFromPath(path);
  if (!fd.is_valid())
    return ConstructDartObject(kFromFileResult, ToDart(ZX_ERR_IO));

  struct stat stat_struct;
  if (fstat(fd.get(), &stat_struct) == -1)
    return ConstructDartObject(kFromFileResult, ToDart(ZX_ERR_IO));
  zx_handle_t vmo = ZX_HANDLE_INVALID;
  zx_status_t status = fdio_get_vmo_clone(fd.get(), &vmo);
  if (status != ZX_OK)
    return ConstructDartObject(kFromFileResult, ToDart(status));

  return ConstructDartObject(kFromFileResult, ToDart(status),
                             ToDart(Handle::Create(vmo)),
                             ToDart(stat_struct.st_size));
}

Dart_Handle System::VmoGetSize(fxl::RefPtr<Handle> vmo) {
  if (!vmo || !vmo->is_valid()) {
    return ConstructDartObject(kGetSizeResult, ToDart(ZX_ERR_BAD_HANDLE));
  }

  uint64_t size;
  zx_status_t status = zx_vmo_get_size(vmo->handle(), &size);

  return ConstructDartObject(kGetSizeResult, ToDart(status), ToDart(size));
}

zx_status_t System::VmoSetSize(fxl::RefPtr<Handle> vmo, uint64_t size) {
  if (!vmo || !vmo->is_valid()) {
    return ZX_ERR_BAD_HANDLE;
  }
  return zx_vmo_set_size(vmo->handle(), size);
}

zx_status_t System::VmoWrite(fxl::RefPtr<Handle> vmo,
                             uint64_t offset,
                             const tonic::DartByteData& data) {
  if (!vmo || !vmo->is_valid()) {
    data.Release();
    return ZX_ERR_BAD_HANDLE;
  }

  zx_status_t status =
      zx_vmo_write(vmo->handle(), data.data(), offset, data.length_in_bytes());

  data.Release();
  return status;
}

Dart_Handle System::VmoRead(fxl::RefPtr<Handle> vmo,
                            uint64_t offset,
                            size_t size) {
  if (!vmo || !vmo->is_valid()) {
    return ConstructDartObject(kReadResult, ToDart(ZX_ERR_BAD_HANDLE));
  }

  // TODO: constrain size?
  ByteDataScope bytes(size);
  zx_status_t status = zx_vmo_read(vmo->handle(), bytes.data(), offset, size);
  bytes.Release();
  if (status == ZX_OK) {
    return ConstructDartObject(kReadResult, ToDart(status), bytes.dart_handle(),
                               ToDart(size));
  }
  return ConstructDartObject(kReadResult, ToDart(status));
}

struct SizedRegion {
  SizedRegion(void* r, size_t s) : region(r), size(s) {}
  void* region;
  size_t size;
};

void System::VmoMapFinalizer(void* isolate_callback_data,
                             Dart_WeakPersistentHandle handle,
                             void* peer) {
  SizedRegion* r = reinterpret_cast<SizedRegion*>(peer);
  zx_vmar_unmap(zx_vmar_root_self(), reinterpret_cast<uintptr_t>(r->region),
                r->size);
  delete r;
}

Dart_Handle System::VmoMap(fxl::RefPtr<Handle> vmo) {
  if (!vmo || !vmo->is_valid())
    return ConstructDartObject(kMapResult, ToDart(ZX_ERR_BAD_HANDLE));

  uint64_t size;
  zx_status_t status = zx_vmo_get_size(vmo->handle(), &size);
  if (status != ZX_OK)
    return ConstructDartObject(kMapResult, ToDart(status));

  uintptr_t mapped_addr;
  status = zx_vmar_map(zx_vmar_root_self(), ZX_VM_PERM_READ, 0, vmo->handle(),
                       0, size, &mapped_addr);
  if (status != ZX_OK)
    return ConstructDartObject(kMapResult, ToDart(status));

  void* data = reinterpret_cast<void*>(mapped_addr);
  Dart_Handle object = Dart_NewExternalTypedData(Dart_TypedData_kUint8, data,
                                                 static_cast<intptr_t>(size));
  FXL_DCHECK(!tonic::LogIfError(object));

  SizedRegion* r = new SizedRegion(data, size);
  Dart_NewWeakPersistentHandle(object, reinterpret_cast<void*>(r),
                               static_cast<intptr_t>(size) + sizeof(*r),
                               System::VmoMapFinalizer);

  return ConstructDartObject(kMapResult, ToDart(ZX_OK), object);
}

uint64_t System::ClockGet(uint32_t clock_id) {
  return zx_clock_get(clock_id);
}

// clang-format: off

#define FOR_EACH_STATIC_BINDING(V) \
  V(System, ChannelCreate)         \
  V(System, ChannelFromFile)       \
  V(System, ChannelWrite)          \
  V(System, ChannelQueryAndRead)   \
  V(System, EventpairCreate)       \
  V(System, Reboot)                \
  V(System, SocketCreate)          \
  V(System, SocketWrite)           \
  V(System, SocketRead)            \
  V(System, VmoCreate)             \
  V(System, VmoFromFile)           \
  V(System, VmoGetSize)            \
  V(System, VmoSetSize)            \
  V(System, VmoRead)               \
  V(System, VmoWrite)              \
  V(System, VmoMap)                \
  V(System, ClockGet)

// clang-format: on

// Tonic is missing a comma.
#define DART_REGISTER_NATIVE_STATIC_(CLASS, METHOD) \
  DART_REGISTER_NATIVE_STATIC(CLASS, METHOD),

FOR_EACH_STATIC_BINDING(DART_NATIVE_CALLBACK_STATIC)

void System::RegisterNatives(tonic::DartLibraryNatives* natives) {
  natives->Register({FOR_EACH_STATIC_BINDING(DART_REGISTER_NATIVE_STATIC_)});
}

}  // namespace dart
}  // namespace zircon
