// Copyright 2018 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/inspector/custom-preview.h"

#include "../../third_party/inspector_protocol/crdtp/json.h"
#include "src/debug/debug-interface.h"
#include "src/inspector/injected-script.h"
#include "src/inspector/inspected-context.h"
#include "src/inspector/string-util.h"
#include "src/inspector/v8-console-message.h"
#include "src/inspector/v8-inspector-impl.h"
#include "src/inspector/v8-stack-trace-impl.h"

namespace v8_inspector {

using protocol::Runtime::CustomPreview;

namespace {
void reportError(v8::Local<v8::Context> context, const v8::TryCatch& tryCatch) {
  DCHECK(tryCatch.HasCaught());
  v8::Isolate* isolate = context->GetIsolate();
  V8InspectorImpl* inspector =
      static_cast<V8InspectorImpl*>(v8::debug::GetInspector(isolate));
  int contextId = InspectedContext::contextId(context);
  int groupId = inspector->contextGroupId(contextId);
  v8::Local<v8::String> message = tryCatch.Message()->Get();
  v8::Local<v8::String> prefix =
      toV8String(isolate, "Custom Formatter Failed: ");
  message = v8::String::Concat(isolate, prefix, message);
  std::vector<v8::Local<v8::Value>> arguments;
  arguments.push_back(message);
  V8ConsoleMessageStorage* storage =
      inspector->ensureConsoleMessageStorage(groupId);
  if (!storage) return;
  storage->addMessage(V8ConsoleMessage::createForConsoleAPI(
      context, contextId, groupId, inspector,
      inspector->client()->currentTimeMS(), ConsoleAPIType::kError, arguments,
      String16(), nullptr));
}

void reportError(v8::Local<v8::Context> context, const v8::TryCatch& tryCatch,
                 const String16& message) {
  v8::Isolate* isolate = context->GetIsolate();
  isolate->ThrowException(toV8String(isolate, message));
  reportError(context, tryCatch);
}

InjectedScript* getInjectedScript(v8::Local<v8::Context> context,
                                  int sessionId) {
  v8::Isolate* isolate = context->GetIsolate();
  V8InspectorImpl* inspector =
      static_cast<V8InspectorImpl*>(v8::debug::GetInspector(isolate));
  InspectedContext* inspectedContext =
      inspector->getContext(InspectedContext::contextId(context));
  if (!inspectedContext) return nullptr;
  return inspectedContext->getInjectedScript(sessionId);
}

bool substituteObjectTags(int sessionId, const String16& groupName,
                          v8::Local<v8::Context> context,
                          v8::Local<v8::Array> jsonML, int maxDepth) {
  if (!jsonML->Length()) return true;
  v8::Isolate* isolate = context->GetIsolate();
  v8::TryCatch tryCatch(isolate);

  if (maxDepth <= 0) {
    reportError(context, tryCatch,
                "Too deep hierarchy of inlined custom previews");
    return false;
  }

  v8::Local<v8::Value> firstValue;
  if (!jsonML->Get(context, 0).ToLocal(&firstValue)) {
    reportError(context, tryCatch);
    return false;
  }
  v8::Local<v8::String> objectLiteral = toV8String(isolate, "object");
  if (jsonML->Length() == 2 && firstValue->IsString() &&
      firstValue.As<v8::String>()->StringEquals(objectLiteral)) {
    v8::Local<v8::Value> attributesValue;
    if (!jsonML->Get(context, 1).ToLocal(&attributesValue)) {
      reportError(context, tryCatch);
      return false;
    }
    if (!attributesValue->IsObject()) {
      reportError(context, tryCatch, "attributes should be an Object");
      return false;
    }
    v8::Local<v8::Object> attributes = attributesValue.As<v8::Object>();
    v8::Local<v8::Value> originValue;
    if (!attributes->Get(context, objectLiteral).ToLocal(&originValue)) {
      reportError(context, tryCatch);
      return false;
    }
    if (originValue->IsUndefined()) {
      reportError(context, tryCatch,
                  "obligatory attribute \"object\" isn't specified");
      return false;
    }

    v8::Local<v8::Value> configValue;
    if (!attributes->Get(context, toV8String(isolate, "config"))
             .ToLocal(&configValue)) {
      reportError(context, tryCatch);
      return false;
    }

    InjectedScript* injectedScript = getInjectedScript(context, sessionId);
    if (!injectedScript) {
      reportError(context, tryCatch, "cannot find context with specified id");
      return false;
    }
    std::unique_ptr<protocol::Runtime::RemoteObject> wrapper;
    protocol::Response response =
        injectedScript->wrapObject(originValue, groupName, WrapMode::kNoPreview,
                                   configValue, maxDepth - 1, &wrapper);
    if (!response.IsSuccess() || !wrapper) {
      reportError(context, tryCatch, "cannot wrap value");
      return false;
    }
    std::vector<uint8_t> json;
    v8_crdtp::json::ConvertCBORToJSON(v8_crdtp::SpanFrom(wrapper->Serialize()),
                                      &json);
    v8::Local<v8::Value> jsonWrapper;
    v8_inspector::StringView serialized(json.data(), json.size());
    if (!v8::JSON::Parse(context, toV8String(isolate, serialized))
             .ToLocal(&jsonWrapper)) {
      reportError(context, tryCatch, "cannot wrap value");
      return false;
    }
    if (jsonML->Set(context, 1, jsonWrapper).IsNothing()) {
      reportError(context, tryCatch);
      return false;
    }
  } else {
    for (uint32_t i = 0; i < jsonML->Length(); ++i) {
      v8::Local<v8::Value> value;
      if (!jsonML->Get(context, i).ToLocal(&value)) {
        reportError(context, tryCatch);
        return false;
      }
      if (value->IsArray() && value.As<v8::Array>()->Length() > 0 &&
          !substituteObjectTags(sessionId, groupName, context,
                                value.As<v8::Array>(), maxDepth - 1)) {
        return false;
      }
    }
  }
  return true;
}

void bodyCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::TryCatch tryCatch(isolate);
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  v8::Local<v8::Object> bodyConfig = info.Data().As<v8::Object>();

  v8::Local<v8::Value> objectValue;
  if (!bodyConfig->Get(context, toV8String(isolate, "object"))
           .ToLocal(&objectValue)) {
    reportError(context, tryCatch);
    return;
  }
  if (!objectValue->IsObject()) {
    reportError(context, tryCatch, "object should be an Object");
    return;
  }
  v8::Local<v8::Object> object = objectValue.As<v8::Object>();

  v8::Local<v8::Value> formatterValue;
  if (!bodyConfig->Get(context, toV8String(isolate, "formatter"))
           .ToLocal(&formatterValue)) {
    reportError(context, tryCatch);
    return;
  }
  if (!formatterValue->IsObject()) {
    reportError(context, tryCatch, "formatter should be an Object");
    return;
  }
  v8::Local<v8::Object> formatter = formatterValue.As<v8::Object>();

  v8::Local<v8::Value> bodyValue;
  if (!formatter->Get(context, toV8String(isolate, "body"))
           .ToLocal(&bodyValue)) {
    reportError(context, tryCatch);
    return;
  }
  if (!bodyValue->IsFunction()) {
    reportError(context, tryCatch, "body should be a Function");
    return;
  }
  v8::Local<v8::Function> bodyFunction = bodyValue.As<v8::Function>();

  v8::Local<v8::Value> configValue;
  if (!bodyConfig->Get(context, toV8String(isolate, "config"))
           .ToLocal(&configValue)) {
    reportError(context, tryCatch);
    return;
  }

  v8::Local<v8::Value> sessionIdValue;
  if (!bodyConfig->Get(context, toV8String(isolate, "sessionId"))
           .ToLocal(&sessionIdValue)) {
    reportError(context, tryCatch);
    return;
  }
  if (!sessionIdValue->IsInt32()) {
    reportError(context, tryCatch, "sessionId should be an Int32");
    return;
  }

  v8::Local<v8::Value> groupNameValue;
  if (!bodyConfig->Get(context, toV8String(isolate, "groupName"))
           .ToLocal(&groupNameValue)) {
    reportError(context, tryCatch);
    return;
  }
  if (!groupNameValue->IsString()) {
    reportError(context, tryCatch, "groupName should be a string");
    return;
  }

  v8::Local<v8::Value> formattedValue;
  v8::Local<v8::Value> args[] = {object, configValue};
  if (!bodyFunction->Call(context, formatter, 2, args)
           .ToLocal(&formattedValue)) {
    reportError(context, tryCatch);
    return;
  }
  if (!formattedValue->IsArray()) {
    reportError(context, tryCatch, "body should return an Array");
    return;
  }
  v8::Local<v8::Array> jsonML = formattedValue.As<v8::Array>();
  if (jsonML->Length() &&
      !substituteObjectTags(
          sessionIdValue.As<v8::Int32>()->Value(),
          toProtocolString(isolate, groupNameValue.As<v8::String>()), context,
          jsonML, kMaxCustomPreviewDepth)) {
    return;
  }
  info.GetReturnValue().Set(jsonML);
}
}  // anonymous namespace

void generateCustomPreview(int sessionId, const String16& groupName,
                           v8::Local<v8::Object> object,
                           v8::MaybeLocal<v8::Value> maybeConfig, int maxDepth,
                           std::unique_ptr<CustomPreview>* preview) {
  v8::Local<v8::Context> context = object->CreationContext();
  v8::Isolate* isolate = context->GetIsolate();
  v8::MicrotasksScope microtasksScope(isolate,
                                      v8::MicrotasksScope::kDoNotRunMicrotasks);
  v8::TryCatch tryCatch(isolate);

  v8::Local<v8::Value> configValue;
  if (!maybeConfig.ToLocal(&configValue)) configValue = v8::Undefined(isolate);

  v8::Local<v8::Object> global = context->Global();
  v8::Local<v8::Value> formattersValue;
  if (!global->Get(context, toV8String(isolate, "devtoolsFormatters"))
           .ToLocal(&formattersValue)) {
    reportError(context, tryCatch);
    return;
  }
  if (!formattersValue->IsArray()) return;
  v8::Local<v8::Array> formatters = formattersValue.As<v8::Array>();
  v8::Local<v8::String> headerLiteral = toV8String(isolate, "header");
  v8::Local<v8::String> hasBodyLiteral = toV8String(isolate, "hasBody");
  for (uint32_t i = 0; i < formatters->Length(); ++i) {
    v8::Local<v8::Value> formatterValue;
    if (!formatters->Get(context, i).ToLocal(&formatterValue)) {
      reportError(context, tryCatch);
      return;
    }
    if (!formatterValue->IsObject()) {
      reportError(context, tryCatch, "formatter should be an Object");
      return;
    }
    v8::Local<v8::Object> formatter = formatterValue.As<v8::Object>();

    v8::Local<v8::Value> headerValue;
    if (!formatter->Get(context, headerLiteral).ToLocal(&headerValue)) {
      reportError(context, tryCatch);
      return;
    }
    if (!headerValue->IsFunction()) {
      reportError(context, tryCatch, "header should be a Function");
      return;
    }
    v8::Local<v8::Function> headerFunction = headerValue.As<v8::Function>();

    v8::Local<v8::Value> formattedValue;
    v8::Local<v8::Value> args[] = {object, configValue};
    if (!headerFunction->Call(context, formatter, 2, args)
             .ToLocal(&formattedValue)) {
      reportError(context, tryCatch);
      return;
    }
    if (!formattedValue->IsArray()) continue;
    v8::Local<v8::Array> jsonML = formattedValue.As<v8::Array>();

    v8::Local<v8::Value> hasBodyFunctionValue;
    if (!formatter->Get(context, hasBodyLiteral)
             .ToLocal(&hasBodyFunctionValue)) {
      reportError(context, tryCatch);
      return;
    }
    if (!hasBodyFunctionValue->IsFunction()) continue;
    v8::Local<v8::Function> hasBodyFunction =
        hasBodyFunctionValue.As<v8::Function>();
    v8::Local<v8::Value> hasBodyValue;
    if (!hasBodyFunction->Call(context, formatter, 2, args)
             .ToLocal(&hasBodyValue)) {
      reportError(context, tryCatch);
      return;
    }
    bool hasBody = hasBodyValue->ToBoolean(isolate)->Value();

    if (jsonML->Length() && !substituteObjectTags(sessionId, groupName, context,
                                                  jsonML, maxDepth)) {
      return;
    }

    v8::Local<v8::String> header;
    if (!v8::JSON::Stringify(context, jsonML).ToLocal(&header)) {
      reportError(context, tryCatch);
      return;
    }

    v8::Local<v8::Function> bodyFunction;
    if (hasBody) {
      v8::Local<v8::Object> bodyConfig = v8::Object::New(isolate);
      if (bodyConfig
              ->CreateDataProperty(context, toV8String(isolate, "sessionId"),
                                   v8::Integer::New(isolate, sessionId))
              .IsNothing()) {
        reportError(context, tryCatch);
        return;
      }
      if (bodyConfig
              ->CreateDataProperty(context, toV8String(isolate, "formatter"),
                                   formatter)
              .IsNothing()) {
        reportError(context, tryCatch);
        return;
      }
      if (bodyConfig
              ->CreateDataProperty(context, toV8String(isolate, "groupName"),
                                   toV8String(isolate, groupName))
              .IsNothing()) {
        reportError(context, tryCatch);
        return;
      }
      if (bodyConfig
              ->CreateDataProperty(context, toV8String(isolate, "config"),
                                   configValue)
              .IsNothing()) {
        reportError(context, tryCatch);
        return;
      }
      if (bodyConfig
              ->CreateDataProperty(context, toV8String(isolate, "object"),
                                   object)
              .IsNothing()) {
        reportError(context, tryCatch);
        return;
      }
      if (!v8::Function::New(context, bodyCallback, bodyConfig)
               .ToLocal(&bodyFunction)) {
        reportError(context, tryCatch);
        return;
      }
    }
    *preview = CustomPreview::create()
                   .setHeader(toProtocolString(isolate, header))
                   .build();
    if (!bodyFunction.IsEmpty()) {
      InjectedScript* injectedScript = getInjectedScript(context, sessionId);
      if (!injectedScript) {
        reportError(context, tryCatch, "cannot find context with specified id");
        return;
      }
      (*preview)->setBodyGetterId(
          injectedScript->bindObject(bodyFunction, groupName));
    }
    return;
  }
}
}  // namespace v8_inspector
