#include <nan.h>
#include <uv.h>

using namespace Nan;
using v8::FunctionTemplate;

NAN_METHOD(ReturnUndefined) {
  uv_rusage_t rusage;
  int err = uv_getrusage(&rusage);
  if (err) {
    return ThrowError("uv_getrusage failed");
  }

  v8::Local<v8::Object> obj = Nan::New<v8::Object>();
  Nan::Set(obj, Nan::New("userCpuTimeUsedSec").ToLocalChecked(),
           Nan::New<v8::Number>(rusage.ru_utime.tv_sec));
  Nan::Set(obj, Nan::New("userCpuTimeUsedMs").ToLocalChecked(),
           Nan::New<v8::Number>(rusage.ru_utime.tv_usec));
  Nan::Set(obj, Nan::New("systemCpuTimeUsedSec").ToLocalChecked(),
           Nan::New<v8::Number>(rusage.ru_stime.tv_sec));
  Nan::Set(obj, Nan::New("systemCpuTimeUsedMs").ToLocalChecked(),
           Nan::New<v8::Number>(rusage.ru_stime.tv_usec));
  Nan::Set(obj, Nan::New("maxRss").ToLocalChecked(),
           Nan::New<v8::Number>(rusage.ru_maxrss));
  Nan::Set(obj, Nan::New("sharedMemSize").ToLocalChecked(),
           Nan::New<v8::Number>(rusage.ru_ixrss));
  Nan::Set(obj, Nan::New("unsharedDataSize").ToLocalChecked(),
           Nan::New<v8::Number>(rusage.ru_idrss));
  Nan::Set(obj, Nan::New("integralUnsharedStackSize").ToLocalChecked(),
           Nan::New<v8::Number>(rusage.ru_isrss));
  Nan::Set(obj, Nan::New("pageReclaims").ToLocalChecked(),
           Nan::New<v8::Number>(rusage.ru_minflt));
  Nan::Set(obj, Nan::New("pageFaults").ToLocalChecked(),
           Nan::New<v8::Number>(rusage.ru_majflt));
  Nan::Set(obj, Nan::New("swaps").ToLocalChecked(),
           Nan::New<v8::Number>(rusage.ru_nswap));
  Nan::Set(obj, Nan::New("blockInputOps").ToLocalChecked(),
           Nan::New<v8::Number>(rusage.ru_inblock));
  Nan::Set(obj, Nan::New("blockOutputOps").ToLocalChecked(),
           Nan::New<v8::Number>(rusage.ru_oublock));
  Nan::Set(obj, Nan::New("ipcMsgSent").ToLocalChecked(),
           Nan::New<v8::Number>(rusage.ru_msgsnd));
  Nan::Set(obj, Nan::New("ipcMsgReceived").ToLocalChecked(),
           Nan::New<v8::Number>(rusage.ru_msgrcv));
  Nan::Set(obj, Nan::New("signalsReceived").ToLocalChecked(),
           Nan::New<v8::Number>(rusage.ru_nsignals));
  Nan::Set(obj, Nan::New("voluntaryContextSwitches").ToLocalChecked(),
           Nan::New<v8::Number>(rusage.ru_nvcsw));
  Nan::Set(obj, Nan::New("involuntaryContextSwitches").ToLocalChecked(),
           Nan::New<v8::Number>(rusage.ru_nivcsw));

  info.GetReturnValue().Set(obj);
}

NAN_MODULE_INIT(Init) {
  Nan::Set(target, Nan::New("rusage").ToLocalChecked(),
           Nan::GetFunction(Nan::New<FunctionTemplate>(ReturnUndefined))
               .ToLocalChecked());
}

NODE_MODULE(hello, Init)
