// 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/pwa.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 PWA {

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

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

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

CRDTP_BEGIN_DESERIALIZER(FileHandlerAccept)
    CRDTP_DESERIALIZE_FIELD("fileExtensions", m_fileExtensions),
    CRDTP_DESERIALIZE_FIELD("mediaType", m_mediaType),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(FileHandlerAccept)
    CRDTP_SERIALIZE_FIELD("mediaType", m_mediaType);
    CRDTP_SERIALIZE_FIELD("fileExtensions", m_fileExtensions);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(FileHandler)
    CRDTP_DESERIALIZE_FIELD("accepts", m_accepts),
    CRDTP_DESERIALIZE_FIELD("action", m_action),
    CRDTP_DESERIALIZE_FIELD("displayName", m_displayName),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(FileHandler)
    CRDTP_SERIALIZE_FIELD("action", m_action);
    CRDTP_SERIALIZE_FIELD("accepts", m_accepts);
    CRDTP_SERIALIZE_FIELD("displayName", m_displayName);
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 getOsAppState(crdtp::Dispatchable& dispatchable);
    void install(crdtp::Dispatchable& dispatchable);
    void uninstall(crdtp::Dispatchable& dispatchable);
    void launch(crdtp::Dispatchable& dispatchable);
    void launchFilesInApp(crdtp::Dispatchable& dispatchable);
    void openCurrentPageInApp(crdtp::Dispatchable& dispatchable);
    void changeAppUserSettings(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("changeAppUserSettings"),
          &DomainDispatcherImpl::changeAppUserSettings
    },
    {
          crdtp::SpanFrom("getOsAppState"),
          &DomainDispatcherImpl::getOsAppState
    },
    {
          crdtp::SpanFrom("install"),
          &DomainDispatcherImpl::install
    },
    {
          crdtp::SpanFrom("launch"),
          &DomainDispatcherImpl::launch
    },
    {
          crdtp::SpanFrom("launchFilesInApp"),
          &DomainDispatcherImpl::launchFilesInApp
    },
    {
          crdtp::SpanFrom("openCurrentPageInApp"),
          &DomainDispatcherImpl::openCurrentPageInApp
    },
    {
          crdtp::SpanFrom("uninstall"),
          &DomainDispatcherImpl::uninstall
    },
    };
    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;
}


class GetOsAppStateCallbackImpl : public Backend::GetOsAppStateCallback, public DomainDispatcher::Callback {
public:
    GetOsAppStateCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("PWA.getOsAppState")) { }

    void sendSuccess(int badgeCount, std::unique_ptr<protocol::Array<protocol::PWA::FileHandler>> fileHandlers) override
    {
        crdtp::ObjectSerializer serializer;
        serializer.AddField(crdtp::MakeSpan("badgeCount"), badgeCount);
        serializer.AddField(crdtp::MakeSpan("fileHandlers"), fileHandlers);
        sendIfActive(serializer.Finish(), DispatchResponse::Success());
    }

    void fallThrough() override
    {
        fallThroughIfActive();
    }

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

namespace {

struct getOsAppStateParams : public crdtp::DeserializableProtocolObject<getOsAppStateParams> {
    String manifestId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(getOsAppStateParams)
    CRDTP_DESERIALIZE_FIELD("manifestId", manifestId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->GetOsAppState(params.manifestId, std::make_unique<GetOsAppStateCallbackImpl>(weakPtr(), dispatchable));
}

class InstallCallbackImpl : public Backend::InstallCallback, public DomainDispatcher::Callback {
public:
    InstallCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("PWA.install")) { }

    void sendSuccess() override
    {
        crdtp::ObjectSerializer serializer;
        sendIfActive(serializer.Finish(), DispatchResponse::Success());
    }

    void fallThrough() override
    {
        fallThroughIfActive();
    }

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

namespace {

struct installParams : public crdtp::DeserializableProtocolObject<installParams> {
    String manifestId;
    std::optional<String> installUrlOrBundleUrl;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(installParams)
    CRDTP_DESERIALIZE_FIELD_OPT("installUrlOrBundleUrl", installUrlOrBundleUrl),
    CRDTP_DESERIALIZE_FIELD("manifestId", manifestId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->Install(params.manifestId, std::move(params.installUrlOrBundleUrl), std::make_unique<InstallCallbackImpl>(weakPtr(), dispatchable));
}

class UninstallCallbackImpl : public Backend::UninstallCallback, public DomainDispatcher::Callback {
public:
    UninstallCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("PWA.uninstall")) { }

    void sendSuccess() override
    {
        crdtp::ObjectSerializer serializer;
        sendIfActive(serializer.Finish(), DispatchResponse::Success());
    }

    void fallThrough() override
    {
        fallThroughIfActive();
    }

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

namespace {

struct uninstallParams : public crdtp::DeserializableProtocolObject<uninstallParams> {
    String manifestId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(uninstallParams)
    CRDTP_DESERIALIZE_FIELD("manifestId", manifestId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->Uninstall(params.manifestId, std::make_unique<UninstallCallbackImpl>(weakPtr(), dispatchable));
}

class LaunchCallbackImpl : public Backend::LaunchCallback, public DomainDispatcher::Callback {
public:
    LaunchCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("PWA.launch")) { }

    void sendSuccess(const String& targetId) override
    {
        crdtp::ObjectSerializer serializer;
        serializer.AddField(crdtp::MakeSpan("targetId"), targetId);
        sendIfActive(serializer.Finish(), DispatchResponse::Success());
    }

    void fallThrough() override
    {
        fallThroughIfActive();
    }

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

namespace {

struct launchParams : public crdtp::DeserializableProtocolObject<launchParams> {
    String manifestId;
    std::optional<String> url;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(launchParams)
    CRDTP_DESERIALIZE_FIELD("manifestId", manifestId),
    CRDTP_DESERIALIZE_FIELD_OPT("url", url),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->Launch(params.manifestId, std::move(params.url), std::make_unique<LaunchCallbackImpl>(weakPtr(), dispatchable));
}

class LaunchFilesInAppCallbackImpl : public Backend::LaunchFilesInAppCallback, public DomainDispatcher::Callback {
public:
    LaunchFilesInAppCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("PWA.launchFilesInApp")) { }

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

    void fallThrough() override
    {
        fallThroughIfActive();
    }

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

namespace {

struct launchFilesInAppParams : public crdtp::DeserializableProtocolObject<launchFilesInAppParams> {
    String manifestId;
    std::unique_ptr<protocol::Array<String>> files;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(launchFilesInAppParams)
    CRDTP_DESERIALIZE_FIELD("files", files),
    CRDTP_DESERIALIZE_FIELD("manifestId", manifestId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->LaunchFilesInApp(params.manifestId, std::move(params.files), std::make_unique<LaunchFilesInAppCallbackImpl>(weakPtr(), dispatchable));
}

namespace {

struct openCurrentPageInAppParams : public crdtp::DeserializableProtocolObject<openCurrentPageInAppParams> {
    String manifestId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(openCurrentPageInAppParams)
    CRDTP_DESERIALIZE_FIELD("manifestId", manifestId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

class ChangeAppUserSettingsCallbackImpl : public Backend::ChangeAppUserSettingsCallback, public DomainDispatcher::Callback {
public:
    ChangeAppUserSettingsCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("PWA.changeAppUserSettings")) { }

    void sendSuccess() override
    {
        crdtp::ObjectSerializer serializer;
        sendIfActive(serializer.Finish(), DispatchResponse::Success());
    }

    void fallThrough() override
    {
        fallThroughIfActive();
    }

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

namespace {

struct changeAppUserSettingsParams : public crdtp::DeserializableProtocolObject<changeAppUserSettingsParams> {
    String manifestId;
    std::optional<bool> linkCapturing;
    std::optional<String> displayMode;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(changeAppUserSettingsParams)
    CRDTP_DESERIALIZE_FIELD_OPT("displayMode", displayMode),
    CRDTP_DESERIALIZE_FIELD_OPT("linkCapturing", linkCapturing),
    CRDTP_DESERIALIZE_FIELD("manifestId", manifestId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->ChangeAppUserSettings(params.manifestId, std::move(params.linkCapturing), std::move(params.displayMode), std::make_unique<ChangeAppUserSettingsCallbackImpl>(weakPtr(), dispatchable));
}

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("PWA"), SortedRedirects(), std::move(dispatcher));
}

} // PWA
} // namespace protocol
