// Copyright 2018 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/script/v8c/v8c_script_debugger.h"

#include <memory>
#include <sstream>
#include <string>

#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/v8c_tracing_controller.h"
#include "include/inspector/Runtime.h"  // generated
#include "nb/memory_scope.h"
#include "v8/include/libplatform/v8-tracing.h"
#include "v8/include/v8-inspector.h"
#include "v8/third_party/inspector_protocol/encoding/encoding.h"

namespace cobalt {
namespace script {
namespace v8c {

namespace {
constexpr const char* kInspectorDomains[] = {
    "Runtime", "Debugger", "Profiler",
};

constexpr int kContextGroupId = 1;
constexpr char kContextName[] = "Cobalt";

// The following implementation is based on Platform in V8's encoding_test.cc.
class CobaltJsonPlatform
    : public v8_inspector_protocol_encoding::json::Platform {
  bool StrToD(const char* str, double* result) const override {
    return base::StringToDouble(std::string(str), result);
  }
  std::unique_ptr<char[]> DToStr(double value) const override {
    std::string str = base::NumberToString(value);
    if (str.empty()) return nullptr;
    std::unique_ptr<char[]> result(new char[str.length() + 1]);
    SbMemoryCopy(result.get(), str.data(), str.length() + 1);
    DCHECK_EQ(0, result[str.length()]);
    return result;
  }
};

V8cTracingController* GetTracingController() {
  return base::polymorphic_downcast<V8cTracingController*>(
      IsolateFellowship::GetInstance()->platform->GetTracingController());
}

// Inspired by |CopyCharsUnsigned| in v8/src/utils.h
std::string FromStringView(const v8_inspector::StringView& string_view) {
  std::string string;
  if (string_view.is8Bit()) {
    string.assign(reinterpret_cast<const char*>(string_view.characters8()),
                  string_view.length());
  } else {
    string.reserve(string_view.length());
    const uint16_t* chars =
        reinterpret_cast<const uint16_t*>(string_view.characters16());
    for (int i = 0; i < string_view.length(); i++) {
      string += chars[i];
    }
  }
  return string;
}

v8_inspector::StringView ToStringView(const std::string& string) {
  return v8_inspector::StringView(
      reinterpret_cast<const uint8_t*>(string.c_str()), string.length());
}

}  // namespace

V8cScriptDebugger::V8cScriptDebugger(
    V8cGlobalEnvironment* v8c_global_environment, Delegate* delegate)
    : global_environment_(v8c_global_environment),
      delegate_(delegate),
      supported_domains_(std::begin(kInspectorDomains),
                         std::end(kInspectorDomains)),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          inspector_(v8_inspector::V8Inspector::create(
              global_environment_->isolate(), /* client */ this))),
      pause_on_exception_state_(kAll) {
  // Register our one-and-only context with the inspector.
  v8::Isolate* isolate = global_environment_->isolate();
  EntryScope entry_scope(isolate);
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  inspector_->contextCreated(v8_inspector::V8ContextInfo(
      context, kContextGroupId,
      v8_inspector::StringView(reinterpret_cast<const uint8_t*>(kContextName),
                               sizeof(kContextName) - 1)));
}

V8cScriptDebugger::~V8cScriptDebugger() {}

void V8cScriptDebugger::Attach(const std::string& state) {
  DCHECK(!inspector_session_);
  inspector_session_ =
      inspector_->connect(kContextGroupId, this, ToStringView(state));
}

std::string V8cScriptDebugger::Detach() {
  // First inform the inspector that the context is destroyed. This will send
  // an event to inform the DevTools frontend just before we kill the session.
  v8::Isolate* isolate = global_environment_->isolate();
  EntryScope entry_scope(isolate);
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  inspector_->contextDestroyed(context);

  // After the frontend knows the context is destroyed we can kill the session.
  // If/when we re-attach we'll connect a new session and the V8 inspector will
  // then inform the frontend about the sources, etc. in the new context.
  DCHECK(inspector_session_);
  std::vector<uint8_t> state = inspector_session_->state();
  inspector_session_.reset();
  CobaltJsonPlatform platform;
  std::string state_str;
  // TODO: there might be an opportunity to utilize the already encoded json to
  // reduce network traffic size on the wire.
  v8_inspector_protocol_encoding::json::ConvertCBORToJSON(
      platform,
      v8_inspector_protocol_encoding::span<uint8_t>(state.data(), state.size()),
      &state_str);
  return state_str;
}

bool V8cScriptDebugger::EvaluateDebuggerScript(const std::string& js_code,
                                               std::string* out_result_utf8) {
  TRACK_MEMORY_SCOPE("Javascript");
  TRACE_EVENT0("cobalt::script", "V8cScriptDebugger::EvaluateDebuggerScript()");

  v8::Isolate* isolate = global_environment_->isolate();
  EntryScope entry_scope(isolate);
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  v8::TryCatch try_catch(isolate);
  v8::MicrotasksScope microtasksScope(isolate,
                                      v8::MicrotasksScope::kDoNotRunMicrotasks);

  v8::Local<v8::String> source;
  if (!v8::String::NewFromUtf8(isolate, js_code.c_str(),
                               v8::NewStringType::kNormal, js_code.length())
           .ToLocal(&source)) {
    LOG(ERROR) << "Failed to convert source code to V8 UTF-8 string.";
    return false;
  }

  v8::Local<v8::Value> result;
  if (!inspector_->compileAndRunInternalScript(context, source)
           .ToLocal(&result)) {
    v8::String::Utf8Value exception(isolate, try_catch.Exception());
    std::string string(*exception, exception.length());
    if (string.empty()) string.assign("Unknown error");
    LOG(ERROR) << "Debugger script error: " << string;
    if (out_result_utf8) {
      out_result_utf8->assign(std::move(string));
    }
    return false;
  }

  if (out_result_utf8) {
    V8cExceptionState exception_state(isolate);
    FromJSValue(isolate, result, kNoConversionFlags, &exception_state,
                out_result_utf8);
  }

  return true;
}

ScriptDebugger::PauseOnExceptionsState V8cScriptDebugger::SetPauseOnExceptions(
    ScriptDebugger::PauseOnExceptionsState state) {
  DCHECK(inspector_session_);
  auto previous_state = pause_on_exception_state_;
  pause_on_exception_state_ = state;
  inspector_session_->setSkipAllPauses(state == kNone);
  return previous_state;
}

bool V8cScriptDebugger::DispatchProtocolMessage(const std::string& method,
                                                const std::string& message) {
  DCHECK(inspector_session_);
  if (!inspector_session_->canDispatchMethod(ToStringView(method))) {
    return false;
  }
  inspector_session_->dispatchProtocolMessage(v8_inspector::StringView(
      reinterpret_cast<const uint8_t*>(message.c_str()), message.length()));
  return true;
}

std::string V8cScriptDebugger::CreateRemoteObject(
    const ValueHandleHolder& object, const std::string& group) {
  DCHECK(inspector_session_);
  const V8cValueHandleHolder* v8_value_handle_holder =
      base::polymorphic_downcast<const V8cValueHandleHolder*>(&object);

  v8::Isolate* isolate = v8_value_handle_holder->isolate();
  EntryScope entry_scope(isolate);
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  v8::Local<v8::Value> v8_value = v8_value_handle_holder->v8_value();

  std::unique_ptr<v8_inspector::protocol::Runtime::API::RemoteObject>
      remote_object = inspector_session_->wrapObject(
          context, v8_value, ToStringView(group), false /*generatePreview*/);
  return FromStringView(remote_object->toJSONString()->string());
}

const script::ValueHandleHolder* V8cScriptDebugger::LookupRemoteObjectId(
    const std::string& object_id) {
  DCHECK(inspector_session_);

  v8::Isolate* isolate = global_environment_->isolate();
  EntryScope entry_scope(isolate);
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  V8cExceptionState exception_state(isolate);

  std::unique_ptr<v8_inspector::StringBuffer> error;
  v8::Local<v8::Value> v8_value;
  if (!inspector_session_->unwrapObject(&error, ToStringView(object_id),
                                        &v8_value, &context,
                                        nullptr /*objectGroup*/)) {
    std::string err_string = FromStringView(error->string());
    exception_state.SetSimpleException(kRangeError, "%s", err_string.c_str());
    return nullptr;
  }

  std::unique_ptr<V8cValueHandleHolder> holder(new V8cValueHandleHolder());
  FromJSValue(isolate, v8_value, 0 /*conversion_flags*/, &exception_state,
              holder.get());

  V8cValueHandleHolder* retval = holder.get();
  // Keep the scoped_ptr alive in a no-op task so the holder stays valid until
  // the bindings code gets the v8::Value out of it through the raw pointer.
  base::MessageLoop::current()->task_runner()->PostTask(
      FROM_HERE, base::Bind([](std::unique_ptr<V8cValueHandleHolder>) {},
                            base::Passed(&holder)));
  return retval;
}

void V8cScriptDebugger::StartTracing(const std::vector<std::string>& categories,
                                     TraceDelegate* trace_delegate) {
  V8cTracingController* tracing_controller = GetTracingController();
  CHECK(tracing_controller);
  tracing_controller->StartTracing(categories, trace_delegate);
}

void V8cScriptDebugger::StopTracing() {
  V8cTracingController* tracing_controller = GetTracingController();
  CHECK(tracing_controller);
  tracing_controller->StopTracing();
}

void V8cScriptDebugger::AsyncTaskScheduled(const void* task,
                                           const std::string& name,
                                           bool recurring) {
  inspector_->asyncTaskScheduled(ToStringView(name), const_cast<void*>(task),
                                 recurring);
}

void V8cScriptDebugger::AsyncTaskStarted(const void* task) {
  inspector_->asyncTaskStarted(const_cast<void*>(task));
}

void V8cScriptDebugger::AsyncTaskFinished(const void* task) {
  inspector_->asyncTaskFinished(const_cast<void*>(task));
}

void V8cScriptDebugger::AsyncTaskCanceled(const void* task) {
  inspector_->asyncTaskCanceled(const_cast<void*>(task));
}

void V8cScriptDebugger::AllAsyncTasksCanceled() {
  inspector_->allAsyncTasksCanceled();
}

// v8_inspector::V8InspectorClient implementation.
void V8cScriptDebugger::runMessageLoopOnPause(int contextGroupId) {
  DCHECK(contextGroupId == kContextGroupId);
  delegate_->OnScriptDebuggerPause();
}

// v8_inspector::V8InspectorClient implementation.
void V8cScriptDebugger::quitMessageLoopOnPause() {
  delegate_->OnScriptDebuggerResume();
}

// v8_inspector::V8InspectorClient implementation.
void V8cScriptDebugger::runIfWaitingForDebugger(int contextGroupId) {
  delegate_->OnScriptDebuggerResume();
}

// v8_inspector::V8InspectorClient implementation.
std::unique_ptr<v8_inspector::StringBuffer> V8cScriptDebugger::valueSubtype(
    v8::Local<v8::Value> value) {
  if (value->IsNullOrUndefined() || !value->IsObject()) {
    return nullptr;
  }

  v8::Local<v8::Object> object = value.As<v8::Object>();
  if (!WrapperPrivate::HasWrapperPrivate(object)) {
    return nullptr;
  }

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  DCHECK(wrapper_private);
  Wrappable::JSObjectType type =
      wrapper_private->raw_wrappable()->GetJSObjectType();
  if (type == Wrappable::JSObjectType::kNode) {
    return v8_inspector::StringBuffer::create(ToStringView("node"));
  } else if (type == Wrappable::JSObjectType::kArray) {
    return v8_inspector::StringBuffer::create(ToStringView("array"));
  } else if (type == Wrappable::JSObjectType::kError) {
    return v8_inspector::StringBuffer::create(ToStringView("error"));
  } else if (type == Wrappable::JSObjectType::kBlob) {
    return v8_inspector::StringBuffer::create(ToStringView("blob"));
  }
  return nullptr;
}

// v8_inspector::V8InspectorClient implementation.
void V8cScriptDebugger::consoleAPIMessage(
    int contextGroupId, v8::Isolate::MessageErrorLevel level,
    const v8_inspector::StringView& message,
    const v8_inspector::StringView& url, unsigned lineNumber,
    unsigned columnNumber, v8_inspector::V8StackTrace* trace) {
  std::string source;
  if (url.length()) {
    std::ostringstream oss;
    oss << ": " << FromStringView(url) << ", Line " << lineNumber << ", Col "
        << columnNumber;
    source = oss.str();
  }

  std::string msg(FromStringView(message));
  switch (level) {
    case v8::Isolate::kMessageLog:
      LOG(INFO) << "[console.log()" << source << "] " << msg;
      break;
    case v8::Isolate::kMessageDebug:
      LOG(INFO) << "[console.debug()" << source << "] " << msg;
      break;
    case v8::Isolate::kMessageInfo:
      LOG(INFO) << "[console.info()" << source << "] " << msg;
      break;
    case v8::Isolate::kMessageError:
      LOG(ERROR) << "[console.error()" << source << "] " << msg;
      break;
    case v8::Isolate::kMessageWarning:
      LOG(WARNING) << "[console.warn()" << source << "] " << msg;
      break;
    case v8::Isolate::kMessageAll:
      NOTIMPLEMENTED() << "Invalid MessageErrorLevel";
      break;
  }
}

// v8_inspector::V8InspectorClient implementation.
v8::Local<v8::Context> V8cScriptDebugger::ensureDefaultContextInGroup(
    int contextGroupId) {
  v8::Isolate* isolate = global_environment_->isolate();
  EntryScope entry_scope(isolate);
  if (contextGroupId == kContextGroupId) {
    return isolate->GetCurrentContext();
  }
  DLOG(WARNING) << "No default context for group " << contextGroupId;
  return v8::Local<v8::Context>();
}

// v8_inspector::V8Inspector::Channel implementation.
void V8cScriptDebugger::sendResponse(
    int callId, std::unique_ptr<v8_inspector::StringBuffer> message) {
  std::string response = FromStringView(message->string());
  delegate_->OnScriptDebuggerResponse(response);
}

// v8_inspector::V8Inspector::Channel implementation.
void V8cScriptDebugger::sendNotification(
    std::unique_ptr<v8_inspector::StringBuffer> message) {
  std::string event = FromStringView(message->string());
  delegate_->OnScriptDebuggerEvent(event);
}

}  // namespace v8c

// Static factory method declared in public interface.
std::unique_ptr<ScriptDebugger> ScriptDebugger::CreateDebugger(
    GlobalEnvironment* global_environment, Delegate* delegate) {
  auto* v8c_global_environment =
      base::polymorphic_downcast<v8c::V8cGlobalEnvironment*>(
          global_environment);
  return std::unique_ptr<ScriptDebugger>(
      new v8c::V8cScriptDebugger(v8c_global_environment, delegate));
}

}  // namespace script
}  // namespace cobalt
