// This file is generated by TypeBuilder_cpp.template.

// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/devtools/protocol/debugger.h"

#include "content/browser/devtools/protocol/protocol.h"

#include "third_party/inspector_protocol/crdtp/cbor.h"
#include "third_party/inspector_protocol/crdtp/find_by_first.h"
#include "third_party/inspector_protocol/crdtp/span.h"

namespace content {
namespace protocol {
namespace Debugger {

using crdtp::DeserializerState;
using crdtp::FallthroughCallback;
using crdtp::ProtocolTypeTraits;

// ------------- Enum values from types.

const char Metainfo::domainName[] = "Debugger";
const char Metainfo::commandPrefix[] = "Debugger.";
const char Metainfo::version[] = "1.3";



CRDTP_BEGIN_DESERIALIZER(Location)
    CRDTP_DESERIALIZE_FIELD_OPT("columnNumber", m_columnNumber),
    CRDTP_DESERIALIZE_FIELD("lineNumber", m_lineNumber),
    CRDTP_DESERIALIZE_FIELD("scriptId", m_scriptId),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(Location)
    CRDTP_SERIALIZE_FIELD("scriptId", m_scriptId);
    CRDTP_SERIALIZE_FIELD("lineNumber", m_lineNumber);
    CRDTP_SERIALIZE_FIELD("columnNumber", m_columnNumber);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(CallFrame)
    CRDTP_DESERIALIZE_FIELD("callFrameId", m_callFrameId),
    CRDTP_DESERIALIZE_FIELD_OPT("canBeRestarted", m_canBeRestarted),
    CRDTP_DESERIALIZE_FIELD_OPT("functionLocation", m_functionLocation),
    CRDTP_DESERIALIZE_FIELD("functionName", m_functionName),
    CRDTP_DESERIALIZE_FIELD("location", m_location),
    CRDTP_DESERIALIZE_FIELD_OPT("returnValue", m_returnValue),
    CRDTP_DESERIALIZE_FIELD("scopeChain", m_scopeChain),
    CRDTP_DESERIALIZE_FIELD("this", m_this),
    CRDTP_DESERIALIZE_FIELD("url", m_url),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(CallFrame)
    CRDTP_SERIALIZE_FIELD("callFrameId", m_callFrameId);
    CRDTP_SERIALIZE_FIELD("functionName", m_functionName);
    CRDTP_SERIALIZE_FIELD("functionLocation", m_functionLocation);
    CRDTP_SERIALIZE_FIELD("location", m_location);
    CRDTP_SERIALIZE_FIELD("url", m_url);
    CRDTP_SERIALIZE_FIELD("scopeChain", m_scopeChain);
    CRDTP_SERIALIZE_FIELD("this", m_this);
    CRDTP_SERIALIZE_FIELD("returnValue", m_returnValue);
    CRDTP_SERIALIZE_FIELD("canBeRestarted", m_canBeRestarted);
CRDTP_END_SERIALIZER();



const char* Scope::TypeEnum::Global = "global";
const char* Scope::TypeEnum::Local = "local";
const char* Scope::TypeEnum::With = "with";
const char* Scope::TypeEnum::Closure = "closure";
const char* Scope::TypeEnum::Catch = "catch";
const char* Scope::TypeEnum::Block = "block";
const char* Scope::TypeEnum::Script = "script";
const char* Scope::TypeEnum::Eval = "eval";
const char* Scope::TypeEnum::Module = "module";
const char* Scope::TypeEnum::WasmExpressionStack = "wasm-expression-stack";
CRDTP_BEGIN_DESERIALIZER(Scope)
    CRDTP_DESERIALIZE_FIELD_OPT("endLocation", m_endLocation),
    CRDTP_DESERIALIZE_FIELD_OPT("name", m_name),
    CRDTP_DESERIALIZE_FIELD("object", m_object),
    CRDTP_DESERIALIZE_FIELD_OPT("startLocation", m_startLocation),
    CRDTP_DESERIALIZE_FIELD("type", m_type),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(Scope)
    CRDTP_SERIALIZE_FIELD("type", m_type);
    CRDTP_SERIALIZE_FIELD("object", m_object);
    CRDTP_SERIALIZE_FIELD("name", m_name);
    CRDTP_SERIALIZE_FIELD("startLocation", m_startLocation);
    CRDTP_SERIALIZE_FIELD("endLocation", m_endLocation);
CRDTP_END_SERIALIZER();




const char* DebugSymbols::TypeEnum::SourceMap = "SourceMap";
const char* DebugSymbols::TypeEnum::EmbeddedDWARF = "EmbeddedDWARF";
const char* DebugSymbols::TypeEnum::ExternalDWARF = "ExternalDWARF";
CRDTP_BEGIN_DESERIALIZER(DebugSymbols)
    CRDTP_DESERIALIZE_FIELD_OPT("externalURL", m_externalURL),
    CRDTP_DESERIALIZE_FIELD("type", m_type),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(DebugSymbols)
    CRDTP_SERIALIZE_FIELD("type", m_type);
    CRDTP_SERIALIZE_FIELD("externalURL", m_externalURL);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(ResolvedBreakpoint)
    CRDTP_DESERIALIZE_FIELD("breakpointId", m_breakpointId),
    CRDTP_DESERIALIZE_FIELD("location", m_location),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(ResolvedBreakpoint)
    CRDTP_SERIALIZE_FIELD("breakpointId", m_breakpointId);
    CRDTP_SERIALIZE_FIELD("location", m_location);
CRDTP_END_SERIALIZER();


// ------------- Enum values from params.


// ------------- Frontend notifications.

void Frontend::BreakpointResolved(const String& breakpointId, std::unique_ptr<protocol::Debugger::Location> location)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("breakpointId"), breakpointId);
    serializer.AddField(crdtp::MakeSpan("location"), location);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Debugger.breakpointResolved", serializer.Finish()));
}

void Frontend::Paused(std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>> callFrames, const String& reason, std::unique_ptr<protocol::DictionaryValue> data, std::unique_ptr<protocol::Array<String>> hitBreakpoints, std::unique_ptr<protocol::Runtime::StackTrace> asyncStackTrace, std::unique_ptr<protocol::Runtime::StackTraceId> asyncStackTraceId, std::unique_ptr<protocol::Runtime::StackTraceId> asyncCallStackTraceId)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("callFrames"), callFrames);
    serializer.AddField(crdtp::MakeSpan("reason"), reason);
    serializer.AddField(crdtp::MakeSpan("data"), data);
    serializer.AddField(crdtp::MakeSpan("hitBreakpoints"), hitBreakpoints);
    serializer.AddField(crdtp::MakeSpan("asyncStackTrace"), asyncStackTrace);
    serializer.AddField(crdtp::MakeSpan("asyncStackTraceId"), asyncStackTraceId);
    serializer.AddField(crdtp::MakeSpan("asyncCallStackTraceId"), asyncCallStackTraceId);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Debugger.paused", serializer.Finish()));
}

void Frontend::Resumed()
{
    if (!frontend_channel_)
        return;
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Debugger.resumed"));
}

void Frontend::ScriptFailedToParse(const String& scriptId, const String& url, int startLine, int startColumn, int endLine, int endColumn, int executionContextId, const String& hash, const String& buildId, std::unique_ptr<protocol::DictionaryValue> executionContextAuxData, std::optional<String> sourceMapURL, std::optional<bool> hasSourceURL, std::optional<bool> isModule, std::optional<int> length, std::unique_ptr<protocol::Runtime::StackTrace> stackTrace, std::optional<int> codeOffset, std::optional<String> scriptLanguage, std::optional<String> embedderName)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("scriptId"), scriptId);
    serializer.AddField(crdtp::MakeSpan("url"), url);
    serializer.AddField(crdtp::MakeSpan("startLine"), startLine);
    serializer.AddField(crdtp::MakeSpan("startColumn"), startColumn);
    serializer.AddField(crdtp::MakeSpan("endLine"), endLine);
    serializer.AddField(crdtp::MakeSpan("endColumn"), endColumn);
    serializer.AddField(crdtp::MakeSpan("executionContextId"), executionContextId);
    serializer.AddField(crdtp::MakeSpan("hash"), hash);
    serializer.AddField(crdtp::MakeSpan("buildId"), buildId);
    serializer.AddField(crdtp::MakeSpan("executionContextAuxData"), executionContextAuxData);
    serializer.AddField(crdtp::MakeSpan("sourceMapURL"), sourceMapURL);
    serializer.AddField(crdtp::MakeSpan("hasSourceURL"), hasSourceURL);
    serializer.AddField(crdtp::MakeSpan("isModule"), isModule);
    serializer.AddField(crdtp::MakeSpan("length"), length);
    serializer.AddField(crdtp::MakeSpan("stackTrace"), stackTrace);
    serializer.AddField(crdtp::MakeSpan("codeOffset"), codeOffset);
    serializer.AddField(crdtp::MakeSpan("scriptLanguage"), scriptLanguage);
    serializer.AddField(crdtp::MakeSpan("embedderName"), embedderName);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Debugger.scriptFailedToParse", serializer.Finish()));
}

void Frontend::ScriptParsed(const String& scriptId, const String& url, int startLine, int startColumn, int endLine, int endColumn, int executionContextId, const String& hash, const String& buildId, std::unique_ptr<protocol::DictionaryValue> executionContextAuxData, std::optional<bool> isLiveEdit, std::optional<String> sourceMapURL, std::optional<bool> hasSourceURL, std::optional<bool> isModule, std::optional<int> length, std::unique_ptr<protocol::Runtime::StackTrace> stackTrace, std::optional<int> codeOffset, std::optional<String> scriptLanguage, std::unique_ptr<protocol::Array<protocol::Debugger::DebugSymbols>> debugSymbols, std::optional<String> embedderName, std::unique_ptr<protocol::Array<protocol::Debugger::ResolvedBreakpoint>> resolvedBreakpoints)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("scriptId"), scriptId);
    serializer.AddField(crdtp::MakeSpan("url"), url);
    serializer.AddField(crdtp::MakeSpan("startLine"), startLine);
    serializer.AddField(crdtp::MakeSpan("startColumn"), startColumn);
    serializer.AddField(crdtp::MakeSpan("endLine"), endLine);
    serializer.AddField(crdtp::MakeSpan("endColumn"), endColumn);
    serializer.AddField(crdtp::MakeSpan("executionContextId"), executionContextId);
    serializer.AddField(crdtp::MakeSpan("hash"), hash);
    serializer.AddField(crdtp::MakeSpan("buildId"), buildId);
    serializer.AddField(crdtp::MakeSpan("executionContextAuxData"), executionContextAuxData);
    serializer.AddField(crdtp::MakeSpan("isLiveEdit"), isLiveEdit);
    serializer.AddField(crdtp::MakeSpan("sourceMapURL"), sourceMapURL);
    serializer.AddField(crdtp::MakeSpan("hasSourceURL"), hasSourceURL);
    serializer.AddField(crdtp::MakeSpan("isModule"), isModule);
    serializer.AddField(crdtp::MakeSpan("length"), length);
    serializer.AddField(crdtp::MakeSpan("stackTrace"), stackTrace);
    serializer.AddField(crdtp::MakeSpan("codeOffset"), codeOffset);
    serializer.AddField(crdtp::MakeSpan("scriptLanguage"), scriptLanguage);
    serializer.AddField(crdtp::MakeSpan("debugSymbols"), debugSymbols);
    serializer.AddField(crdtp::MakeSpan("embedderName"), embedderName);
    serializer.AddField(crdtp::MakeSpan("resolvedBreakpoints"), resolvedBreakpoints);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Debugger.scriptParsed", serializer.Finish()));
}

void Frontend::flush()
{
    frontend_channel_->FlushProtocolNotifications();
}

void Frontend::sendRawNotification(std::unique_ptr<Serializable> notification)
{
    frontend_channel_->SendProtocolNotification(std::move(notification));
}

// --------------------- Dispatcher.

class DomainDispatcherImpl : public protocol::DomainDispatcher {
public:
    DomainDispatcherImpl(FrontendChannel* frontendChannel, Backend* backend)
        : DomainDispatcher(frontendChannel)
        , m_backend(backend) {}
    ~DomainDispatcherImpl() override { }

    using CallHandler = void (DomainDispatcherImpl::*)(crdtp::Dispatchable& dispatchable);

    bool Dispatch(crdtp::span<uint8_t> command_name, crdtp::Dispatchable& dispatchable) override;

    void removeBreakpoint(crdtp::Dispatchable& dispatchable);
    void setBreakpointByUrl(crdtp::Dispatchable& dispatchable);
 protected:
    Backend* m_backend;
};

namespace {
// This helper method with a static map of command methods (instance methods
// of DomainDispatcherImpl declared just above) by their name is used immediately below,
// in the DomainDispatcherImpl::Dispatch method.
DomainDispatcherImpl::CallHandler CommandByName(crdtp::span<uint8_t> command_name) {
  static auto* commands = [](){
    auto* commands = new std::vector<std::pair<crdtp::span<uint8_t>,
                              DomainDispatcherImpl::CallHandler>>{
    {
          crdtp::SpanFrom("removeBreakpoint"),
          &DomainDispatcherImpl::removeBreakpoint
    },
    {
          crdtp::SpanFrom("setBreakpointByUrl"),
          &DomainDispatcherImpl::setBreakpointByUrl
    },
    };
    return commands;
  }();
  return crdtp::FindByFirst<DomainDispatcherImpl::CallHandler>(*commands, command_name, nullptr);
}
}  // namespace

bool DomainDispatcherImpl::Dispatch(crdtp::span<uint8_t> command_name, crdtp::Dispatchable& dispatchable) {
  CallHandler handler = CommandByName(command_name);
  if (!handler) return false;

  (this->*handler)(dispatchable);
  return true;
}


namespace {

struct removeBreakpointParams : public crdtp::DeserializableProtocolObject<removeBreakpointParams> {
    String breakpointId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(removeBreakpointParams)
    CRDTP_DESERIALIZE_FIELD("breakpointId", breakpointId),
CRDTP_END_DESERIALIZER()

}  // namespace

void DomainDispatcherImpl::removeBreakpoint(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.
    auto deserializer = crdtp::DeferredMessage::FromSpan(dispatchable.Params())->MakeDeserializer();
    removeBreakpointParams params;
    if (!removeBreakpointParams::Deserialize(&deserializer, &params)) {
      ReportInvalidParams(dispatchable, deserializer);
      return;
    }

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->RemoveBreakpoint(params.breakpointId);
    if (response.IsFallThrough()) {
        dispatchable.DispatchFallThrough(response.Message());
        return;
    }
    if (weak->get())
        weak->get()->sendResponse(dispatchable.CallId(), response);
    return;
}

namespace {

struct setBreakpointByUrlParams : public crdtp::DeserializableProtocolObject<setBreakpointByUrlParams> {
    int lineNumber;
    std::optional<String> url;
    std::optional<String> urlRegex;
    std::optional<String> scriptHash;
    std::optional<int> columnNumber;
    std::optional<String> condition;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(setBreakpointByUrlParams)
    CRDTP_DESERIALIZE_FIELD_OPT("columnNumber", columnNumber),
    CRDTP_DESERIALIZE_FIELD_OPT("condition", condition),
    CRDTP_DESERIALIZE_FIELD("lineNumber", lineNumber),
    CRDTP_DESERIALIZE_FIELD_OPT("scriptHash", scriptHash),
    CRDTP_DESERIALIZE_FIELD_OPT("url", url),
    CRDTP_DESERIALIZE_FIELD_OPT("urlRegex", urlRegex),
CRDTP_END_DESERIALIZER()

}  // namespace

void DomainDispatcherImpl::setBreakpointByUrl(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.
    auto deserializer = crdtp::DeferredMessage::FromSpan(dispatchable.Params())->MakeDeserializer();
    setBreakpointByUrlParams params;
    if (!setBreakpointByUrlParams::Deserialize(&deserializer, &params)) {
      ReportInvalidParams(dispatchable, deserializer);
      return;
    }
    // Declare output parameters.
    String out_breakpointId;
    std::unique_ptr<protocol::Array<protocol::Debugger::Location>> out_locations;

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->SetBreakpointByUrl(params.lineNumber, std::move(params.url), std::move(params.urlRegex), std::move(params.scriptHash), std::move(params.columnNumber), std::move(params.condition), &out_breakpointId, &out_locations);
    if (response.IsFallThrough()) {
        dispatchable.DispatchFallThrough(response.Message());
        return;
    }
      if (weak->get()) {
        std::unique_ptr<crdtp::Serializable> result;
        if (response.IsSuccess()) {
          crdtp::ObjectSerializer serializer;
          serializer.AddField(crdtp::MakeSpan("breakpointId"), out_breakpointId);
          serializer.AddField(crdtp::MakeSpan("locations"), out_locations);
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
    return;
}

namespace {
// This helper method (with a static map of redirects) is used from Dispatcher::wire
// immediately below.
const std::vector<std::pair<crdtp::span<uint8_t>, crdtp::span<uint8_t>>>& SortedRedirects() {
  static auto* redirects = [](){
    auto* redirects = new std::vector<std::pair<crdtp::span<uint8_t>, crdtp::span<uint8_t>>>{
    };
    return redirects;
  }();
  return *redirects;
}
}  // namespace

// static
void Dispatcher::wire(UberDispatcher* uber, Backend* backend)
{
    auto dispatcher = std::make_unique<DomainDispatcherImpl>(uber->channel(), backend);
    uber->WireBackend(crdtp::SpanFrom("Debugger"), SortedRedirects(), std::move(dispatcher));
}

} // Debugger
} // namespace content
} // namespace protocol
