// 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/storage.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 Storage {

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

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

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



CRDTP_BEGIN_DESERIALIZER(StorageBucket)
    CRDTP_DESERIALIZE_FIELD_OPT("name", m_name),
    CRDTP_DESERIALIZE_FIELD("storageKey", m_storageKey),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(StorageBucket)
    CRDTP_SERIALIZE_FIELD("storageKey", m_storageKey);
    CRDTP_SERIALIZE_FIELD("name", m_name);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(StorageBucketInfo)
    CRDTP_DESERIALIZE_FIELD("bucket", m_bucket),
    CRDTP_DESERIALIZE_FIELD("durability", m_durability),
    CRDTP_DESERIALIZE_FIELD("expiration", m_expiration),
    CRDTP_DESERIALIZE_FIELD("id", m_id),
    CRDTP_DESERIALIZE_FIELD("persistent", m_persistent),
    CRDTP_DESERIALIZE_FIELD("quota", m_quota),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(StorageBucketInfo)
    CRDTP_SERIALIZE_FIELD("bucket", m_bucket);
    CRDTP_SERIALIZE_FIELD("id", m_id);
    CRDTP_SERIALIZE_FIELD("expiration", m_expiration);
    CRDTP_SERIALIZE_FIELD("quota", m_quota);
    CRDTP_SERIALIZE_FIELD("persistent", m_persistent);
    CRDTP_SERIALIZE_FIELD("durability", m_durability);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(RelatedWebsiteSet)
    CRDTP_DESERIALIZE_FIELD("associatedSites", m_associatedSites),
    CRDTP_DESERIALIZE_FIELD("primarySites", m_primarySites),
    CRDTP_DESERIALIZE_FIELD("serviceSites", m_serviceSites),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(RelatedWebsiteSet)
    CRDTP_SERIALIZE_FIELD("primarySites", m_primarySites);
    CRDTP_SERIALIZE_FIELD("associatedSites", m_associatedSites);
    CRDTP_SERIALIZE_FIELD("serviceSites", m_serviceSites);
CRDTP_END_SERIALIZER();


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


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

void Frontend::CacheStorageContentUpdated(const String& origin, const String& storageKey, const String& bucketId, const String& cacheName)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("origin"), origin);
    serializer.AddField(crdtp::MakeSpan("storageKey"), storageKey);
    serializer.AddField(crdtp::MakeSpan("bucketId"), bucketId);
    serializer.AddField(crdtp::MakeSpan("cacheName"), cacheName);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Storage.cacheStorageContentUpdated", serializer.Finish()));
}

void Frontend::CacheStorageListUpdated(const String& origin, const String& storageKey, const String& bucketId)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("origin"), origin);
    serializer.AddField(crdtp::MakeSpan("storageKey"), storageKey);
    serializer.AddField(crdtp::MakeSpan("bucketId"), bucketId);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Storage.cacheStorageListUpdated", serializer.Finish()));
}

void Frontend::IndexedDBContentUpdated(const String& origin, const String& storageKey, const String& bucketId, const String& databaseName, const String& objectStoreName)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("origin"), origin);
    serializer.AddField(crdtp::MakeSpan("storageKey"), storageKey);
    serializer.AddField(crdtp::MakeSpan("bucketId"), bucketId);
    serializer.AddField(crdtp::MakeSpan("databaseName"), databaseName);
    serializer.AddField(crdtp::MakeSpan("objectStoreName"), objectStoreName);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Storage.indexedDBContentUpdated", serializer.Finish()));
}

void Frontend::IndexedDBListUpdated(const String& origin, const String& storageKey, const String& bucketId)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("origin"), origin);
    serializer.AddField(crdtp::MakeSpan("storageKey"), storageKey);
    serializer.AddField(crdtp::MakeSpan("bucketId"), bucketId);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Storage.indexedDBListUpdated", serializer.Finish()));
}

void Frontend::StorageBucketCreatedOrUpdated(std::unique_ptr<protocol::Storage::StorageBucketInfo> bucketInfo)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("bucketInfo"), bucketInfo);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Storage.storageBucketCreatedOrUpdated", serializer.Finish()));
}

void Frontend::StorageBucketDeleted(const String& bucketId)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("bucketId"), bucketId);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Storage.storageBucketDeleted", 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 runBounceTrackingMitigations(crdtp::Dispatchable& dispatchable);
    void getRelatedWebsiteSets(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("getRelatedWebsiteSets"),
          &DomainDispatcherImpl::getRelatedWebsiteSets
    },
    {
          crdtp::SpanFrom("runBounceTrackingMitigations"),
          &DomainDispatcherImpl::runBounceTrackingMitigations
    },
    };
    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 RunBounceTrackingMitigationsCallbackImpl : public Backend::RunBounceTrackingMitigationsCallback, public DomainDispatcher::Callback {
public:
    RunBounceTrackingMitigationsCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Storage.runBounceTrackingMitigations")) { }

    void sendSuccess(std::unique_ptr<protocol::Array<String>> deletedSites) override
    {
        crdtp::ObjectSerializer serializer;
        serializer.AddField(crdtp::MakeSpan("deletedSites"), deletedSites);
        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::runBounceTrackingMitigations(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.

    m_backend->RunBounceTrackingMitigations(std::make_unique<RunBounceTrackingMitigationsCallbackImpl>(weakPtr(), dispatchable));
}

class GetRelatedWebsiteSetsCallbackImpl : public Backend::GetRelatedWebsiteSetsCallback, public DomainDispatcher::Callback {
public:
    GetRelatedWebsiteSetsCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Storage.getRelatedWebsiteSets")) { }

    void sendSuccess(std::unique_ptr<protocol::Array<protocol::Storage::RelatedWebsiteSet>> sets) override
    {
        crdtp::ObjectSerializer serializer;
        serializer.AddField(crdtp::MakeSpan("sets"), sets);
        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::getRelatedWebsiteSets(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.

    m_backend->GetRelatedWebsiteSets(std::make_unique<GetRelatedWebsiteSetsCallbackImpl>(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("Storage"), SortedRedirects(), std::move(dispatcher));
}

} // Storage
} // namespace protocol
