// Copyright Joyent, Inc. and other Node contributors.
//
// 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 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 "env-inl.h"
#include "node_external_reference.h"
#include "string_bytes.h"

#ifdef __MINGW32__
# include <io.h>
#endif  // __MINGW32__

#ifdef __POSIX__
# include <unistd.h>        // gethostname, sysconf
# include <climits>         // PATH_MAX on Solaris.
#endif  // __POSIX__

#include <array>
#include <cerrno>
#include <cstring>

namespace node {
namespace os {

using v8::Array;
using v8::ArrayBuffer;
using v8::Boolean;
using v8::Context;
using v8::Float64Array;
using v8::FunctionCallbackInfo;
using v8::Int32;
using v8::Integer;
using v8::Isolate;
using v8::Local;
using v8::MaybeLocal;
using v8::NewStringType;
using v8::Null;
using v8::Number;
using v8::Object;
using v8::String;
using v8::Value;


static void GetHostname(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  char buf[UV_MAXHOSTNAMESIZE];
  size_t size = sizeof(buf);
  int r = uv_os_gethostname(buf, &size);

  if (r != 0) {
    CHECK_GE(args.Length(), 1);
    env->CollectUVExceptionInfo(args[args.Length() - 1], r,
                                "uv_os_gethostname");
    return args.GetReturnValue().SetUndefined();
  }

  args.GetReturnValue().Set(
      String::NewFromUtf8(env->isolate(), buf).ToLocalChecked());
}

static void GetOSInformation(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  uv_utsname_t info;
  int err = 0;
#ifdef __Fuchsia__
  // TODO(victor): Update uv_os_uname to get these informations for Fuchsia
  info.sysname[0] = 0;
  info.version[0] = 0;
  info.release[0] = 0;
#else
  err = uv_os_uname(&info);
#endif

  if (err != 0) {
    CHECK_GE(args.Length(), 1);
    env->CollectUVExceptionInfo(args[args.Length() - 1], err, "uv_os_uname");
    return args.GetReturnValue().SetUndefined();
  }

  // [sysname, version, release]
  Local<Value> osInformation[] = {
    String::NewFromUtf8(env->isolate(), info.sysname).ToLocalChecked(),
    String::NewFromUtf8(env->isolate(), info.version).ToLocalChecked(),
    String::NewFromUtf8(env->isolate(), info.release).ToLocalChecked()
  };

  args.GetReturnValue().Set(Array::New(env->isolate(),
                                       osInformation,
                                       arraysize(osInformation)));
}

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

  uv_cpu_info_t* cpu_infos;
  int count;

  int err = uv_cpu_info(&cpu_infos, &count);
  if (err)
    return;

  // It's faster to create an array packed with all the data and
  // assemble them into objects in JS than to call Object::Set() repeatedly
  // The array is in the format
  // [model, speed, (5 entries of cpu_times), model2, speed2, ...]
  std::vector<Local<Value>> result;
  result.reserve(count * 7);
  for (int i = 0; i < count; i++) {
    uv_cpu_info_t* ci = cpu_infos + i;
    result.emplace_back(OneByteString(isolate, ci->model));
    result.emplace_back(Number::New(isolate, ci->speed));
    result.emplace_back(
        Number::New(isolate, static_cast<double>(ci->cpu_times.user)));
    result.emplace_back(
        Number::New(isolate, static_cast<double>(ci->cpu_times.nice)));
    result.emplace_back(
        Number::New(isolate, static_cast<double>(ci->cpu_times.sys)));
    result.emplace_back(
        Number::New(isolate, static_cast<double>(ci->cpu_times.idle)));
    result.emplace_back(
        Number::New(isolate, static_cast<double>(ci->cpu_times.irq)));
  }

  uv_free_cpu_info(cpu_infos, count);
  args.GetReturnValue().Set(Array::New(isolate, result.data(), result.size()));
}


static void GetFreeMemory(const FunctionCallbackInfo<Value>& args) {
  double amount = static_cast<double>(uv_get_free_memory());
  args.GetReturnValue().Set(amount);
}


static void GetTotalMemory(const FunctionCallbackInfo<Value>& args) {
  double amount = static_cast<double>(uv_get_total_memory());
  args.GetReturnValue().Set(amount);
}


static void GetUptime(const FunctionCallbackInfo<Value>& args) {
  double uptime;
  int err = uv_uptime(&uptime);
  if (err == 0)
    args.GetReturnValue().Set(uptime);
}


static void GetLoadAvg(const FunctionCallbackInfo<Value>& args) {
  CHECK(args[0]->IsFloat64Array());
  Local<Float64Array> array = args[0].As<Float64Array>();
  CHECK_EQ(array->Length(), 3);
  Local<ArrayBuffer> ab = array->Buffer();
  double* loadavg = static_cast<double*>(ab->Data());
  uv_loadavg(loadavg);
}


static void GetInterfaceAddresses(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  Isolate* isolate = env->isolate();
  uv_interface_address_t* interfaces;
  int count, i;
  char ip[INET6_ADDRSTRLEN];
  char netmask[INET6_ADDRSTRLEN];
  std::array<char, 18> mac;
  Local<String> name, family;

  int err = uv_interface_addresses(&interfaces, &count);

  if (err == UV_ENOSYS)
    return args.GetReturnValue().SetUndefined();

  if (err) {
    CHECK_GE(args.Length(), 1);
    env->CollectUVExceptionInfo(args[args.Length() - 1], errno,
                                "uv_interface_addresses");
    return args.GetReturnValue().SetUndefined();
  }

  Local<Value> no_scope_id = Integer::New(isolate, -1);
  std::vector<Local<Value>> result;
  result.reserve(count * 7);
  for (i = 0; i < count; i++) {
    const char* const raw_name = interfaces[i].name;

    // Use UTF-8 on both Windows and Unixes (While it may be true that UNIX
    // systems are somewhat encoding-agnostic here, it’s more than reasonable
    // to assume UTF8 as the default as well. It’s what people will expect if
    // they name the interface from any input that uses UTF-8, which should be
    // the most frequent case by far these days.)
    name = String::NewFromUtf8(isolate, raw_name).ToLocalChecked();

    snprintf(mac.data(),
             mac.size(),
             "%02x:%02x:%02x:%02x:%02x:%02x",
             static_cast<unsigned char>(interfaces[i].phys_addr[0]),
             static_cast<unsigned char>(interfaces[i].phys_addr[1]),
             static_cast<unsigned char>(interfaces[i].phys_addr[2]),
             static_cast<unsigned char>(interfaces[i].phys_addr[3]),
             static_cast<unsigned char>(interfaces[i].phys_addr[4]),
             static_cast<unsigned char>(interfaces[i].phys_addr[5]));

    if (interfaces[i].address.address4.sin_family == AF_INET) {
      uv_ip4_name(&interfaces[i].address.address4, ip, sizeof(ip));
      uv_ip4_name(&interfaces[i].netmask.netmask4, netmask, sizeof(netmask));
      family = env->ipv4_string();
    } else if (interfaces[i].address.address4.sin_family == AF_INET6) {
      uv_ip6_name(&interfaces[i].address.address6, ip, sizeof(ip));
      uv_ip6_name(&interfaces[i].netmask.netmask6, netmask, sizeof(netmask));
      family = env->ipv6_string();
    } else {
      strncpy(ip, "<unknown sa family>", INET6_ADDRSTRLEN);
      family = env->unknown_string();
    }

    result.emplace_back(name);
    result.emplace_back(OneByteString(isolate, ip));
    result.emplace_back(OneByteString(isolate, netmask));
    result.emplace_back(family);
    result.emplace_back(FIXED_ONE_BYTE_STRING(isolate, mac));
    result.emplace_back(
        interfaces[i].is_internal ? True(isolate) : False(isolate));
    if (interfaces[i].address.address4.sin_family == AF_INET6) {
      uint32_t scopeid = interfaces[i].address.address6.sin6_scope_id;
      result.emplace_back(Integer::NewFromUnsigned(isolate, scopeid));
    } else {
      result.emplace_back(no_scope_id);
    }
  }

  uv_free_interface_addresses(interfaces, count);
  args.GetReturnValue().Set(Array::New(isolate, result.data(), result.size()));
}


static void GetHomeDirectory(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  char buf[PATH_MAX];

  size_t len = sizeof(buf);
  const int err = uv_os_homedir(buf, &len);

  if (err) {
    CHECK_GE(args.Length(), 1);
    env->CollectUVExceptionInfo(args[args.Length() - 1], err, "uv_os_homedir");
    return args.GetReturnValue().SetUndefined();
  }

  Local<String> home = String::NewFromUtf8(env->isolate(),
                                           buf,
                                           NewStringType::kNormal,
                                           len).ToLocalChecked();
  args.GetReturnValue().Set(home);
}


static void GetUserInfo(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  uv_passwd_t pwd;
  enum encoding encoding;

  if (args[0]->IsObject()) {
    Local<Object> options = args[0].As<Object>();
    MaybeLocal<Value> maybe_encoding = options->Get(env->context(),
                                                    env->encoding_string());
    Local<Value> encoding_opt;
    if (!maybe_encoding.ToLocal(&encoding_opt))
        return;

    encoding = ParseEncoding(env->isolate(), encoding_opt, UTF8);
  } else {
    encoding = UTF8;
  }

  const int err = uv_os_get_passwd(&pwd);

  if (err) {
    CHECK_GE(args.Length(), 2);
    env->CollectUVExceptionInfo(args[args.Length() - 1], err,
                                "uv_os_get_passwd");
    return args.GetReturnValue().SetUndefined();
  }

  auto free_passwd = OnScopeLeave([&]() { uv_os_free_passwd(&pwd); });

  Local<Value> error;

  Local<Value> uid = Number::New(env->isolate(), pwd.uid);
  Local<Value> gid = Number::New(env->isolate(), pwd.gid);
  MaybeLocal<Value> username = StringBytes::Encode(env->isolate(),
                                                   pwd.username,
                                                   encoding,
                                                   &error);
  MaybeLocal<Value> homedir = StringBytes::Encode(env->isolate(),
                                                  pwd.homedir,
                                                  encoding,
                                                  &error);
  MaybeLocal<Value> shell;

  if (pwd.shell == nullptr)
    shell = Null(env->isolate());
  else
    shell = StringBytes::Encode(env->isolate(), pwd.shell, encoding, &error);

  if (username.IsEmpty() || homedir.IsEmpty() || shell.IsEmpty()) {
    CHECK(!error.IsEmpty());
    env->isolate()->ThrowException(error);
    return;
  }

  Local<Object> entry = Object::New(env->isolate());

  entry->Set(env->context(), env->uid_string(), uid).Check();
  entry->Set(env->context(), env->gid_string(), gid).Check();
  entry->Set(env->context(),
             env->username_string(),
             username.ToLocalChecked()).Check();
  entry->Set(env->context(),
             env->homedir_string(),
             homedir.ToLocalChecked()).Check();
  entry->Set(env->context(),
             env->shell_string(),
             shell.ToLocalChecked()).Check();

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

#ifndef __Fuchsia__

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

  CHECK_EQ(args.Length(), 3);
  CHECK(args[0]->IsInt32());
  CHECK(args[1]->IsInt32());

  const int pid = args[0].As<Int32>()->Value();
  const int priority = args[1].As<Int32>()->Value();
  const int err = uv_os_setpriority(pid, priority);

  if (err) {
    CHECK(args[2]->IsObject());
    env->CollectUVExceptionInfo(args[2], err, "uv_os_setpriority");
  }

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


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

  CHECK_EQ(args.Length(), 2);
  CHECK(args[0]->IsInt32());

  const int pid = args[0].As<Int32>()->Value();
  int priority;
  const int err = uv_os_getpriority(pid, &priority);

  if (err) {
    CHECK(args[1]->IsObject());
    env->CollectUVExceptionInfo(args[1], err, "uv_os_getpriority");
    return;
  }

  args.GetReturnValue().Set(priority);
}
#endif // !__Fuchsia__

void Initialize(Local<Object> target,
                Local<Value> unused,
                Local<Context> context,
                void* priv) {
  Environment* env = Environment::GetCurrent(context);
  SetMethod(context, target, "getHostname", GetHostname);
  SetMethod(context, target, "getLoadAvg", GetLoadAvg);
  SetMethod(context, target, "getUptime", GetUptime);
  SetMethod(context, target, "getTotalMem", GetTotalMemory);
  SetMethod(context, target, "getFreeMem", GetFreeMemory);
  SetMethod(context, target, "getCPUs", GetCPUInfo);
  SetMethod(context, target, "getInterfaceAddresses", GetInterfaceAddresses);
  SetMethod(context, target, "getHomeDirectory", GetHomeDirectory);
  SetMethod(context, target, "getUserInfo", GetUserInfo);
  SetMethod(context, target, "setPriority", SetPriority);
  SetMethod(context, target, "getPriority", GetPriority);
  SetMethod(context, target, "getOSInformation", GetOSInformation);
  target
      ->Set(context,
            FIXED_ONE_BYTE_STRING(env->isolate(), "isBigEndian"),
            Boolean::New(env->isolate(), IsBigEndian()))
      .Check();
}

void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
  registry->Register(GetHostname);
  registry->Register(GetLoadAvg);
  registry->Register(GetUptime);
  registry->Register(GetTotalMemory);
  registry->Register(GetFreeMemory);
  registry->Register(GetCPUInfo);
  registry->Register(GetInterfaceAddresses);
  registry->Register(GetHomeDirectory);
  registry->Register(GetUserInfo);
  registry->Register(SetPriority);
  registry->Register(GetPriority);
  registry->Register(GetOSInformation);
}

}  // namespace os
}  // namespace node

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