// 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/extensions.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 Extensions {

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

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

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


CRDTP_BEGIN_DESERIALIZER(ExtensionInfo)
    CRDTP_DESERIALIZE_FIELD("enabled", m_enabled),
    CRDTP_DESERIALIZE_FIELD("id", m_id),
    CRDTP_DESERIALIZE_FIELD("name", m_name),
    CRDTP_DESERIALIZE_FIELD("path", m_path),
    CRDTP_DESERIALIZE_FIELD("version", m_version),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(ExtensionInfo)
    CRDTP_SERIALIZE_FIELD("id", m_id);
    CRDTP_SERIALIZE_FIELD("name", m_name);
    CRDTP_SERIALIZE_FIELD("version", m_version);
    CRDTP_SERIALIZE_FIELD("path", m_path);
    CRDTP_SERIALIZE_FIELD("enabled", m_enabled);
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 triggerAction(crdtp::Dispatchable& dispatchable);
    void loadUnpacked(crdtp::Dispatchable& dispatchable);
    void getExtensions(crdtp::Dispatchable& dispatchable);
    void uninstall(crdtp::Dispatchable& dispatchable);
    void getStorageItems(crdtp::Dispatchable& dispatchable);
    void removeStorageItems(crdtp::Dispatchable& dispatchable);
    void clearStorageItems(crdtp::Dispatchable& dispatchable);
    void setStorageItems(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("clearStorageItems"),
          &DomainDispatcherImpl::clearStorageItems
    },
    {
          crdtp::SpanFrom("getExtensions"),
          &DomainDispatcherImpl::getExtensions
    },
    {
          crdtp::SpanFrom("getStorageItems"),
          &DomainDispatcherImpl::getStorageItems
    },
    {
          crdtp::SpanFrom("loadUnpacked"),
          &DomainDispatcherImpl::loadUnpacked
    },
    {
          crdtp::SpanFrom("removeStorageItems"),
          &DomainDispatcherImpl::removeStorageItems
    },
    {
          crdtp::SpanFrom("setStorageItems"),
          &DomainDispatcherImpl::setStorageItems
    },
    {
          crdtp::SpanFrom("triggerAction"),
          &DomainDispatcherImpl::triggerAction
    },
    {
          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;
}


namespace {

struct triggerActionParams : public crdtp::DeserializableProtocolObject<triggerActionParams> {
    String id;
    String targetId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(triggerActionParams)
    CRDTP_DESERIALIZE_FIELD("id", id),
    CRDTP_DESERIALIZE_FIELD("targetId", targetId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

class LoadUnpackedCallbackImpl : public Backend::LoadUnpackedCallback, public DomainDispatcher::Callback {
public:
    LoadUnpackedCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Extensions.loadUnpacked")) { }

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

    void fallThrough() override
    {
        fallThroughIfActive();
    }

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

namespace {

struct loadUnpackedParams : public crdtp::DeserializableProtocolObject<loadUnpackedParams> {
    String path;
    std::optional<bool> enableInIncognito;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(loadUnpackedParams)
    CRDTP_DESERIALIZE_FIELD_OPT("enableInIncognito", enableInIncognito),
    CRDTP_DESERIALIZE_FIELD("path", path),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->LoadUnpacked(params.path, std::move(params.enableInIncognito), std::make_unique<LoadUnpackedCallbackImpl>(weakPtr(), dispatchable));
}

namespace {


}  // namespace

void DomainDispatcherImpl::getExtensions(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.
    // Declare output parameters.
    std::unique_ptr<protocol::Array<protocol::Extensions::ExtensionInfo>> out_extensions;

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->GetExtensions(&out_extensions);
    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("extensions"), out_extensions);
          result = serializer.Finish();
        } else {
          result = Serializable::From({});
        }
        weak->get()->sendResponse(dispatchable.CallId(), response, std::move(result));
      }
    return;
}

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("Extensions.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 id;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(uninstallParams)
    CRDTP_DESERIALIZE_FIELD("id", id),
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.id, std::make_unique<UninstallCallbackImpl>(weakPtr(), dispatchable));
}

class GetStorageItemsCallbackImpl : public Backend::GetStorageItemsCallback, public DomainDispatcher::Callback {
public:
    GetStorageItemsCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Extensions.getStorageItems")) { }

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

    void fallThrough() override
    {
        fallThroughIfActive();
    }

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

namespace {

struct getStorageItemsParams : public crdtp::DeserializableProtocolObject<getStorageItemsParams> {
    String id;
    String storageArea;
    std::unique_ptr<protocol::Array<String>> keys;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(getStorageItemsParams)
    CRDTP_DESERIALIZE_FIELD("id", id),
    CRDTP_DESERIALIZE_FIELD_OPT("keys", keys),
    CRDTP_DESERIALIZE_FIELD("storageArea", storageArea),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->GetStorageItems(params.id, params.storageArea, std::move(params.keys), std::make_unique<GetStorageItemsCallbackImpl>(weakPtr(), dispatchable));
}

class RemoveStorageItemsCallbackImpl : public Backend::RemoveStorageItemsCallback, public DomainDispatcher::Callback {
public:
    RemoveStorageItemsCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Extensions.removeStorageItems")) { }

    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 removeStorageItemsParams : public crdtp::DeserializableProtocolObject<removeStorageItemsParams> {
    String id;
    String storageArea;
    std::unique_ptr<protocol::Array<String>> keys;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(removeStorageItemsParams)
    CRDTP_DESERIALIZE_FIELD("id", id),
    CRDTP_DESERIALIZE_FIELD("keys", keys),
    CRDTP_DESERIALIZE_FIELD("storageArea", storageArea),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->RemoveStorageItems(params.id, params.storageArea, std::move(params.keys), std::make_unique<RemoveStorageItemsCallbackImpl>(weakPtr(), dispatchable));
}

class ClearStorageItemsCallbackImpl : public Backend::ClearStorageItemsCallback, public DomainDispatcher::Callback {
public:
    ClearStorageItemsCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Extensions.clearStorageItems")) { }

    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 clearStorageItemsParams : public crdtp::DeserializableProtocolObject<clearStorageItemsParams> {
    String id;
    String storageArea;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(clearStorageItemsParams)
    CRDTP_DESERIALIZE_FIELD("id", id),
    CRDTP_DESERIALIZE_FIELD("storageArea", storageArea),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->ClearStorageItems(params.id, params.storageArea, std::make_unique<ClearStorageItemsCallbackImpl>(weakPtr(), dispatchable));
}

class SetStorageItemsCallbackImpl : public Backend::SetStorageItemsCallback, public DomainDispatcher::Callback {
public:
    SetStorageItemsCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Extensions.setStorageItems")) { }

    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 setStorageItemsParams : public crdtp::DeserializableProtocolObject<setStorageItemsParams> {
    String id;
    String storageArea;
    std::unique_ptr<protocol::DictionaryValue> values;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(setStorageItemsParams)
    CRDTP_DESERIALIZE_FIELD("id", id),
    CRDTP_DESERIALIZE_FIELD("storageArea", storageArea),
    CRDTP_DESERIALIZE_FIELD("values", values),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->SetStorageItems(params.id, params.storageArea, std::move(params.values), std::make_unique<SetStorageItemsCallbackImpl>(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("Extensions"), SortedRedirects(), std::move(dispatcher));
}

} // Extensions
} // namespace protocol
