// 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 "chrome/browser/devtools/protocol/page.h"

#include "chrome/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 protocol {
namespace Page {

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

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

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


CRDTP_BEGIN_DESERIALIZER(InstallabilityErrorArgument)
    CRDTP_DESERIALIZE_FIELD("name", m_name),
    CRDTP_DESERIALIZE_FIELD("value", m_value),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(InstallabilityErrorArgument)
    CRDTP_SERIALIZE_FIELD("name", m_name);
    CRDTP_SERIALIZE_FIELD("value", m_value);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(InstallabilityError)
    CRDTP_DESERIALIZE_FIELD("errorArguments", m_errorArguments),
    CRDTP_DESERIALIZE_FIELD("errorId", m_errorId),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(InstallabilityError)
    CRDTP_SERIALIZE_FIELD("errorId", m_errorId);
    CRDTP_SERIALIZE_FIELD("errorArguments", m_errorArguments);
CRDTP_END_SERIALIZER();


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


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

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 disable(crdtp::Dispatchable& dispatchable);
    void enable(crdtp::Dispatchable& dispatchable);
    void getInstallabilityErrors(crdtp::Dispatchable& dispatchable);
    void getManifestIcons(crdtp::Dispatchable& dispatchable);
    void getAppId(crdtp::Dispatchable& dispatchable);
    void printToPDF(crdtp::Dispatchable& dispatchable);
    void setAdBlockingEnabled(crdtp::Dispatchable& dispatchable);
    void setSPCTransactionMode(crdtp::Dispatchable& dispatchable);
    void setRPHRegistrationMode(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("disable"),
          &DomainDispatcherImpl::disable
    },
    {
          crdtp::SpanFrom("enable"),
          &DomainDispatcherImpl::enable
    },
    {
          crdtp::SpanFrom("getAppId"),
          &DomainDispatcherImpl::getAppId
    },
    {
          crdtp::SpanFrom("getInstallabilityErrors"),
          &DomainDispatcherImpl::getInstallabilityErrors
    },
    {
          crdtp::SpanFrom("getManifestIcons"),
          &DomainDispatcherImpl::getManifestIcons
    },
    {
          crdtp::SpanFrom("printToPDF"),
          &DomainDispatcherImpl::printToPDF
    },
    {
          crdtp::SpanFrom("setAdBlockingEnabled"),
          &DomainDispatcherImpl::setAdBlockingEnabled
    },
    {
          crdtp::SpanFrom("setRPHRegistrationMode"),
          &DomainDispatcherImpl::setRPHRegistrationMode
    },
    {
          crdtp::SpanFrom("setSPCTransactionMode"),
          &DomainDispatcherImpl::setSPCTransactionMode
    },
    };
    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 {


}  // namespace

void DomainDispatcherImpl::disable(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.

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

namespace {

struct enableParams : public crdtp::DeserializableProtocolObject<enableParams> {
    std::optional<bool> enableFileChooserOpenedEvent;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(enableParams)
    CRDTP_DESERIALIZE_FIELD_OPT("enableFileChooserOpenedEvent", enableFileChooserOpenedEvent),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

class GetInstallabilityErrorsCallbackImpl : public Backend::GetInstallabilityErrorsCallback, public DomainDispatcher::Callback {
public:
    GetInstallabilityErrorsCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Page.getInstallabilityErrors")) { }

    void sendSuccess(std::unique_ptr<protocol::Array<protocol::Page::InstallabilityError>> installabilityErrors) override
    {
        crdtp::ObjectSerializer serializer;
        serializer.AddField(crdtp::MakeSpan("installabilityErrors"), installabilityErrors);
        sendIfActive(serializer.Finish(), DispatchResponse::Success());
    }

    void fallThrough() override
    {
        fallThroughIfActive();
    }

    void sendFailure(const DispatchResponse& response) override
    {
        DCHECK(response.IsError());
        sendIfActive(nullptr, response);
    }
};

namespace {


}  // namespace

void DomainDispatcherImpl::getInstallabilityErrors(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.

    m_backend->GetInstallabilityErrors(std::make_unique<GetInstallabilityErrorsCallbackImpl>(weakPtr(), dispatchable));
}

class GetManifestIconsCallbackImpl : public Backend::GetManifestIconsCallback, public DomainDispatcher::Callback {
public:
    GetManifestIconsCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Page.getManifestIcons")) { }

    void sendSuccess(std::optional<Binary> primaryIcon) override
    {
        crdtp::ObjectSerializer serializer;
        serializer.AddField(crdtp::MakeSpan("primaryIcon"), primaryIcon);
        sendIfActive(serializer.Finish(), DispatchResponse::Success());
    }

    void fallThrough() override
    {
        fallThroughIfActive();
    }

    void sendFailure(const DispatchResponse& response) override
    {
        DCHECK(response.IsError());
        sendIfActive(nullptr, response);
    }
};

namespace {


}  // namespace

void DomainDispatcherImpl::getManifestIcons(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.

    m_backend->GetManifestIcons(std::make_unique<GetManifestIconsCallbackImpl>(weakPtr(), dispatchable));
}

class GetAppIdCallbackImpl : public Backend::GetAppIdCallback, public DomainDispatcher::Callback {
public:
    GetAppIdCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Page.getAppId")) { }

    void sendSuccess(std::optional<String> appId, std::optional<String> recommendedId) override
    {
        crdtp::ObjectSerializer serializer;
        serializer.AddField(crdtp::MakeSpan("appId"), appId);
        serializer.AddField(crdtp::MakeSpan("recommendedId"), recommendedId);
        sendIfActive(serializer.Finish(), DispatchResponse::Success());
    }

    void fallThrough() override
    {
        fallThroughIfActive();
    }

    void sendFailure(const DispatchResponse& response) override
    {
        DCHECK(response.IsError());
        sendIfActive(nullptr, response);
    }
};

namespace {


}  // namespace

void DomainDispatcherImpl::getAppId(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.

    m_backend->GetAppId(std::make_unique<GetAppIdCallbackImpl>(weakPtr(), dispatchable));
}

class PrintToPDFCallbackImpl : public Backend::PrintToPDFCallback, public DomainDispatcher::Callback {
public:
    PrintToPDFCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Page.printToPDF")) { }

    void sendSuccess(const Binary& data, std::optional<String> stream) override
    {
        crdtp::ObjectSerializer serializer;
        serializer.AddField(crdtp::MakeSpan("data"), data);
        serializer.AddField(crdtp::MakeSpan("stream"), stream);
        sendIfActive(serializer.Finish(), DispatchResponse::Success());
    }

    void fallThrough() override
    {
        fallThroughIfActive();
    }

    void sendFailure(const DispatchResponse& response) override
    {
        DCHECK(response.IsError());
        sendIfActive(nullptr, response);
    }
};

namespace {

struct printToPDFParams : public crdtp::DeserializableProtocolObject<printToPDFParams> {
    std::optional<bool> landscape;
    std::optional<bool> displayHeaderFooter;
    std::optional<bool> printBackground;
    std::optional<double> scale;
    std::optional<double> paperWidth;
    std::optional<double> paperHeight;
    std::optional<double> marginTop;
    std::optional<double> marginBottom;
    std::optional<double> marginLeft;
    std::optional<double> marginRight;
    std::optional<String> pageRanges;
    std::optional<String> headerTemplate;
    std::optional<String> footerTemplate;
    std::optional<bool> preferCSSPageSize;
    std::optional<String> transferMode;
    std::optional<bool> generateTaggedPDF;
    std::optional<bool> generateDocumentOutline;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(printToPDFParams)
    CRDTP_DESERIALIZE_FIELD_OPT("displayHeaderFooter", displayHeaderFooter),
    CRDTP_DESERIALIZE_FIELD_OPT("footerTemplate", footerTemplate),
    CRDTP_DESERIALIZE_FIELD_OPT("generateDocumentOutline", generateDocumentOutline),
    CRDTP_DESERIALIZE_FIELD_OPT("generateTaggedPDF", generateTaggedPDF),
    CRDTP_DESERIALIZE_FIELD_OPT("headerTemplate", headerTemplate),
    CRDTP_DESERIALIZE_FIELD_OPT("landscape", landscape),
    CRDTP_DESERIALIZE_FIELD_OPT("marginBottom", marginBottom),
    CRDTP_DESERIALIZE_FIELD_OPT("marginLeft", marginLeft),
    CRDTP_DESERIALIZE_FIELD_OPT("marginRight", marginRight),
    CRDTP_DESERIALIZE_FIELD_OPT("marginTop", marginTop),
    CRDTP_DESERIALIZE_FIELD_OPT("pageRanges", pageRanges),
    CRDTP_DESERIALIZE_FIELD_OPT("paperHeight", paperHeight),
    CRDTP_DESERIALIZE_FIELD_OPT("paperWidth", paperWidth),
    CRDTP_DESERIALIZE_FIELD_OPT("preferCSSPageSize", preferCSSPageSize),
    CRDTP_DESERIALIZE_FIELD_OPT("printBackground", printBackground),
    CRDTP_DESERIALIZE_FIELD_OPT("scale", scale),
    CRDTP_DESERIALIZE_FIELD_OPT("transferMode", transferMode),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->PrintToPDF(std::move(params.landscape), std::move(params.displayHeaderFooter), std::move(params.printBackground), std::move(params.scale), std::move(params.paperWidth), std::move(params.paperHeight), std::move(params.marginTop), std::move(params.marginBottom), std::move(params.marginLeft), std::move(params.marginRight), std::move(params.pageRanges), std::move(params.headerTemplate), std::move(params.footerTemplate), std::move(params.preferCSSPageSize), std::move(params.transferMode), std::move(params.generateTaggedPDF), std::move(params.generateDocumentOutline), std::make_unique<PrintToPDFCallbackImpl>(weakPtr(), dispatchable));
}

namespace {

struct setAdBlockingEnabledParams : public crdtp::DeserializableProtocolObject<setAdBlockingEnabledParams> {
    bool enabled;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(setAdBlockingEnabledParams)
    CRDTP_DESERIALIZE_FIELD("enabled", enabled),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct setSPCTransactionModeParams : public crdtp::DeserializableProtocolObject<setSPCTransactionModeParams> {
    String mode;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(setSPCTransactionModeParams)
    CRDTP_DESERIALIZE_FIELD("mode", mode),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct setRPHRegistrationModeParams : public crdtp::DeserializableProtocolObject<setRPHRegistrationModeParams> {
    String mode;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(setRPHRegistrationModeParams)
    CRDTP_DESERIALIZE_FIELD("mode", mode),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->SetRPHRegistrationMode(params.mode);
    if (response.IsFallThrough()) {
        dispatchable.DispatchFallThrough(response.Message());
        return;
    }
    if (weak->get())
        weak->get()->sendResponse(dispatchable.CallId(), response);
    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>>>{
          { crdtp::SpanFrom("Page.clearDeviceMetricsOverride"), crdtp::SpanFrom("Emulation.clearDeviceMetricsOverride") },
          { crdtp::SpanFrom("Page.clearDeviceOrientationOverride"), crdtp::SpanFrom("DeviceOrientation.clearDeviceOrientationOverride") },
          { crdtp::SpanFrom("Page.clearGeolocationOverride"), crdtp::SpanFrom("Emulation.clearGeolocationOverride") },
          { crdtp::SpanFrom("Page.deleteCookie"), crdtp::SpanFrom("Network.deleteCookie") },
          { crdtp::SpanFrom("Page.setDeviceMetricsOverride"), crdtp::SpanFrom("Emulation.setDeviceMetricsOverride") },
          { crdtp::SpanFrom("Page.setDeviceOrientationOverride"), crdtp::SpanFrom("DeviceOrientation.setDeviceOrientationOverride") },
          { crdtp::SpanFrom("Page.setGeolocationOverride"), crdtp::SpanFrom("Emulation.setGeolocationOverride") },
          { crdtp::SpanFrom("Page.setTouchEmulationEnabled"), crdtp::SpanFrom("Emulation.setTouchEmulationEnabled") },
    };
    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("Page"), SortedRedirects(), std::move(dispatcher));
}

} // Page
} // namespace protocol
