// Copyright 2019 the V8 project 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 "src/extensions/vtunedomain-support-extension.h"
#include <string>
#include <vector>

namespace v8 {
namespace internal {

namespace libvtune {

int startTask(const std::vector<std::string>& vparams);
int endTask(const std::vector<std::string>& vparams);

const auto& function_map =
    *new std::map<std::string, int (*)(const std::vector<std::string>&)>{
        {"start", startTask}, {"end", endTask}};

void split(const std::string& str, char delimiter,
           std::vector<std::string>* vparams) {
  std::string::size_type baseindex = 0;
  std::string::size_type offindex = str.find(delimiter);

  while (offindex != std::string::npos) {
    (*vparams).push_back(str.substr(baseindex, offindex - baseindex));
    baseindex = ++offindex;
    offindex = str.find(delimiter, offindex);

    if (offindex == std::string::npos)
      (*vparams).push_back(str.substr(baseindex, str.length()));
  }
}

int startTask(const std::vector<std::string>& vparams) {
  int errcode = 0;

  if (const char* domain_name = vparams[1].c_str()) {
    if (const char* task_name = vparams[2].c_str()) {
      if (std::shared_ptr<VTuneDomain> domainptr =
              VTuneDomain::createDomain(domain_name)) {
        if (!domainptr->beginTask(task_name)) {
          errcode += TASK_BEGIN_FAILED;
        }
      } else {
        errcode += CREATE_DOMAIN_FAILED;
      }
    } else {
      errcode += NO_TASK_NAME;
    }

  } else {
    errcode = NO_DOMAIN_NAME;
  }

  return errcode;
}

int endTask(const std::vector<std::string>& vparams) {
  int errcode = 0;

  if (const char* domain_name = vparams[1].c_str()) {
    if (std::shared_ptr<VTuneDomain> domainptr =
            VTuneDomain::createDomain(domain_name)) {
      domainptr->endTask();
    } else {
      errcode += CREATE_DOMAIN_FAILED;
    }
  } else {
    errcode = NO_DOMAIN_NAME;
  }

  return errcode;
}

int invoke(const char* params) {
  int errcode = 0;
  std::vector<std::string> vparams;

  split(*(new std::string(params)), ' ', &vparams);

  auto it = function_map.find(vparams[0]);
  if (it != function_map.end()) {
    (it->second)(vparams);
  } else {
    errcode += UNKNOWN_PARAMS;
  }

  return errcode;
}

}  // namespace libvtune

v8::Local<v8::FunctionTemplate>
VTuneDomainSupportExtension::GetNativeFunctionTemplate(
    v8::Isolate* isolate, v8::Local<v8::String> str) {
  return v8::FunctionTemplate::New(isolate, VTuneDomainSupportExtension::Mark);
}

// args should take three parameters
// %0 : string, which is the domain name. Domain is used to tagging trace data
// for different modules or libraryies in a program
// %1 : string, which is the task name. Task is a logical unit of work performed
// by a particular thread statement. Task can nest.
// %2 : string, "start" / "end". Action to be taken on a task in a particular
// domain
void VTuneDomainSupportExtension::Mark(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  if (args.Length() != 3 || !args[0]->IsString() || !args[1]->IsString() ||
      !args[2]->IsString()) {
    args.GetIsolate()->ThrowException(v8::String::NewFromUtf8Literal(
        args.GetIsolate(),
        "Parameter number should be exactly three, first domain name"
        "second task name, third start/end"));
    return;
  }

  v8::Isolate* isolate = args.GetIsolate();
  v8::String::Utf8Value domainName(isolate, args[0]);
  v8::String::Utf8Value taskName(isolate, args[1]);
  v8::String::Utf8Value statName(isolate, args[2]);

  char* cdomainName = *domainName;
  char* ctaskName = *taskName;
  char* cstatName = *statName;

  std::stringstream params;
  params << cstatName << " " << cdomainName << " " << ctaskName;

  int r = 0;
  if ((r = libvtune::invoke(params.str().c_str())) != 0) {
    args.GetIsolate()->ThrowException(
        v8::String::NewFromUtf8(args.GetIsolate(), std::to_string(r).c_str())
            .ToLocalChecked());
  }
}

}  // namespace internal
}  // namespace v8
