// 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 "components/ui_devtools/css.h"

#include "components/ui_devtools/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 ui_devtools {
namespace protocol {
namespace CSS {

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

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

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


CRDTP_BEGIN_DESERIALIZER(SourceRange)
    CRDTP_DESERIALIZE_FIELD("endColumn", m_endColumn),
    CRDTP_DESERIALIZE_FIELD("endLine", m_endLine),
    CRDTP_DESERIALIZE_FIELD("startColumn", m_startColumn),
    CRDTP_DESERIALIZE_FIELD("startLine", m_startLine),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(SourceRange)
    CRDTP_SERIALIZE_FIELD("startLine", m_startLine);
    CRDTP_SERIALIZE_FIELD("startColumn", m_startColumn);
    CRDTP_SERIALIZE_FIELD("endLine", m_endLine);
    CRDTP_SERIALIZE_FIELD("endColumn", m_endColumn);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(ShorthandEntry)
    CRDTP_DESERIALIZE_FIELD_OPT("important", m_important),
    CRDTP_DESERIALIZE_FIELD("name", m_name),
    CRDTP_DESERIALIZE_FIELD("value", m_value),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(ShorthandEntry)
    CRDTP_SERIALIZE_FIELD("name", m_name);
    CRDTP_SERIALIZE_FIELD("value", m_value);
    CRDTP_SERIALIZE_FIELD("important", m_important);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(CSSStyle)
    CRDTP_DESERIALIZE_FIELD("cssProperties", m_cssProperties),
    CRDTP_DESERIALIZE_FIELD_OPT("range", m_range),
    CRDTP_DESERIALIZE_FIELD("shorthandEntries", m_shorthandEntries),
    CRDTP_DESERIALIZE_FIELD_OPT("styleSheetId", m_styleSheetId),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(CSSStyle)
    CRDTP_SERIALIZE_FIELD("styleSheetId", m_styleSheetId);
    CRDTP_SERIALIZE_FIELD("cssProperties", m_cssProperties);
    CRDTP_SERIALIZE_FIELD("shorthandEntries", m_shorthandEntries);
    CRDTP_SERIALIZE_FIELD("range", m_range);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(CSSProperty)
    CRDTP_DESERIALIZE_FIELD("name", m_name),
    CRDTP_DESERIALIZE_FIELD_OPT("range", m_range),
    CRDTP_DESERIALIZE_FIELD("value", m_value),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(CSSProperty)
    CRDTP_SERIALIZE_FIELD("name", m_name);
    CRDTP_SERIALIZE_FIELD("value", m_value);
    CRDTP_SERIALIZE_FIELD("range", m_range);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(RuleMatch)
    CRDTP_DESERIALIZE_FIELD("matchingSelectors", m_matchingSelectors),
    CRDTP_DESERIALIZE_FIELD("rule", m_rule),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(RuleMatch)
    CRDTP_SERIALIZE_FIELD("rule", m_rule);
    CRDTP_SERIALIZE_FIELD("matchingSelectors", m_matchingSelectors);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(Value)
    CRDTP_DESERIALIZE_FIELD_OPT("range", m_range),
    CRDTP_DESERIALIZE_FIELD("text", m_text),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(Value)
    CRDTP_SERIALIZE_FIELD("text", m_text);
    CRDTP_SERIALIZE_FIELD("range", m_range);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(SelectorList)
    CRDTP_DESERIALIZE_FIELD("selectors", m_selectors),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(SelectorList)
    CRDTP_SERIALIZE_FIELD("selectors", m_selectors);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(CSSStyleSheetHeader)
    CRDTP_DESERIALIZE_FIELD("sourceURL", m_sourceURL),
    CRDTP_DESERIALIZE_FIELD("startColumn", m_startColumn),
    CRDTP_DESERIALIZE_FIELD("startLine", m_startLine),
    CRDTP_DESERIALIZE_FIELD("styleSheetId", m_styleSheetId),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(CSSStyleSheetHeader)
    CRDTP_SERIALIZE_FIELD("styleSheetId", m_styleSheetId);
    CRDTP_SERIALIZE_FIELD("sourceURL", m_sourceURL);
    CRDTP_SERIALIZE_FIELD("startLine", m_startLine);
    CRDTP_SERIALIZE_FIELD("startColumn", m_startColumn);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(CSSRule)
    CRDTP_DESERIALIZE_FIELD("selectorList", m_selectorList),
    CRDTP_DESERIALIZE_FIELD("style", m_style),
    CRDTP_DESERIALIZE_FIELD_OPT("styleSheetId", m_styleSheetId),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(CSSRule)
    CRDTP_SERIALIZE_FIELD("styleSheetId", m_styleSheetId);
    CRDTP_SERIALIZE_FIELD("selectorList", m_selectorList);
    CRDTP_SERIALIZE_FIELD("style", m_style);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(StyleDeclarationEdit)
    CRDTP_DESERIALIZE_FIELD("range", m_range),
    CRDTP_DESERIALIZE_FIELD("styleSheetId", m_styleSheetId),
    CRDTP_DESERIALIZE_FIELD("text", m_text),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(StyleDeclarationEdit)
    CRDTP_SERIALIZE_FIELD("styleSheetId", m_styleSheetId);
    CRDTP_SERIALIZE_FIELD("range", m_range);
    CRDTP_SERIALIZE_FIELD("text", m_text);
CRDTP_END_SERIALIZER();


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


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

void Frontend::styleSheetChanged(const String& styleSheetId)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("styleSheetId"), styleSheetId);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("CSS.styleSheetChanged", serializer.Finish()));
}

void Frontend::styleSheetAdded(std::unique_ptr<protocol::CSS::CSSStyleSheetHeader> header)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("header"), header);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("CSS.styleSheetAdded", 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 disable(crdtp::Dispatchable& dispatchable);
    void enable(crdtp::Dispatchable& dispatchable);
    void getMatchedStylesForNode(crdtp::Dispatchable& dispatchable);
    void getStyleSheetText(crdtp::Dispatchable& dispatchable);
    void setStyleTexts(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("getMatchedStylesForNode"),
          &DomainDispatcherImpl::getMatchedStylesForNode
    },
    {
          crdtp::SpanFrom("getStyleSheetText"),
          &DomainDispatcherImpl::getStyleSheetText
    },
    {
          crdtp::SpanFrom("setStyleTexts"),
          &DomainDispatcherImpl::setStyleTexts
    },
    };
    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 {


}  // namespace

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

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

namespace {

struct getMatchedStylesForNodeParams : public crdtp::DeserializableProtocolObject<getMatchedStylesForNodeParams> {
    int nodeId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(getMatchedStylesForNodeParams)
    CRDTP_DESERIALIZE_FIELD("nodeId", nodeId),
CRDTP_END_DESERIALIZER()

}  // namespace

void DomainDispatcherImpl::getMatchedStylesForNode(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.
    auto deserializer = crdtp::DeferredMessage::FromSpan(dispatchable.Params())->MakeDeserializer();
    getMatchedStylesForNodeParams params;
    if (!getMatchedStylesForNodeParams::Deserialize(&deserializer, &params)) {
      ReportInvalidParams(dispatchable, deserializer);
      return;
    }
    // Declare output parameters.
    std::unique_ptr<protocol::Array<protocol::CSS::RuleMatch>> out_matchedCSSRules;

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

namespace {

struct getStyleSheetTextParams : public crdtp::DeserializableProtocolObject<getStyleSheetTextParams> {
    String styleSheetId;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(getStyleSheetTextParams)
    CRDTP_DESERIALIZE_FIELD("styleSheetId", styleSheetId),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

struct setStyleTextsParams : public crdtp::DeserializableProtocolObject<setStyleTextsParams> {
    std::unique_ptr<protocol::Array<protocol::CSS::StyleDeclarationEdit>> edits;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(setStyleTextsParams)
    CRDTP_DESERIALIZE_FIELD("edits", edits),
CRDTP_END_DESERIALIZER()

}  // namespace

void DomainDispatcherImpl::setStyleTexts(crdtp::Dispatchable& dispatchable)
{
    // Prepare input parameters.
    auto deserializer = crdtp::DeferredMessage::FromSpan(dispatchable.Params())->MakeDeserializer();
    setStyleTextsParams params;
    if (!setStyleTextsParams::Deserialize(&deserializer, &params)) {
      ReportInvalidParams(dispatchable, deserializer);
      return;
    }
    // Declare output parameters.
    std::unique_ptr<protocol::Array<protocol::CSS::CSSStyle>> out_styles;

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->setStyleTexts(std::move(params.edits), &out_styles);
    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("styles"), out_styles);
          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("CSS"), SortedRedirects(), std::move(dispatcher));
}

} // CSS
} // namespace ui_devtools
} // namespace protocol
