// 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 "content/browser/devtools/protocol/input.h"

#include "content/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 content {
namespace protocol {
namespace Input {

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

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

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

CRDTP_BEGIN_DESERIALIZER(TouchPoint)
    CRDTP_DESERIALIZE_FIELD_OPT("force", m_force),
    CRDTP_DESERIALIZE_FIELD_OPT("id", m_id),
    CRDTP_DESERIALIZE_FIELD_OPT("radiusX", m_radiusX),
    CRDTP_DESERIALIZE_FIELD_OPT("radiusY", m_radiusY),
    CRDTP_DESERIALIZE_FIELD_OPT("rotationAngle", m_rotationAngle),
    CRDTP_DESERIALIZE_FIELD_OPT("tangentialPressure", m_tangentialPressure),
    CRDTP_DESERIALIZE_FIELD_OPT("tiltX", m_tiltX),
    CRDTP_DESERIALIZE_FIELD_OPT("tiltY", m_tiltY),
    CRDTP_DESERIALIZE_FIELD_OPT("twist", m_twist),
    CRDTP_DESERIALIZE_FIELD("x", m_x),
    CRDTP_DESERIALIZE_FIELD("y", m_y),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(TouchPoint)
    CRDTP_SERIALIZE_FIELD("x", m_x);
    CRDTP_SERIALIZE_FIELD("y", m_y);
    CRDTP_SERIALIZE_FIELD("radiusX", m_radiusX);
    CRDTP_SERIALIZE_FIELD("radiusY", m_radiusY);
    CRDTP_SERIALIZE_FIELD("rotationAngle", m_rotationAngle);
    CRDTP_SERIALIZE_FIELD("force", m_force);
    CRDTP_SERIALIZE_FIELD("tangentialPressure", m_tangentialPressure);
    CRDTP_SERIALIZE_FIELD("tiltX", m_tiltX);
    CRDTP_SERIALIZE_FIELD("tiltY", m_tiltY);
    CRDTP_SERIALIZE_FIELD("twist", m_twist);
    CRDTP_SERIALIZE_FIELD("id", m_id);
CRDTP_END_SERIALIZER();





CRDTP_BEGIN_DESERIALIZER(DragDataItem)
    CRDTP_DESERIALIZE_FIELD_OPT("baseURL", m_baseURL),
    CRDTP_DESERIALIZE_FIELD("data", m_data),
    CRDTP_DESERIALIZE_FIELD("mimeType", m_mimeType),
    CRDTP_DESERIALIZE_FIELD_OPT("title", m_title),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(DragDataItem)
    CRDTP_SERIALIZE_FIELD("mimeType", m_mimeType);
    CRDTP_SERIALIZE_FIELD("data", m_data);
    CRDTP_SERIALIZE_FIELD("title", m_title);
    CRDTP_SERIALIZE_FIELD("baseURL", m_baseURL);
CRDTP_END_SERIALIZER();


CRDTP_BEGIN_DESERIALIZER(DragData)
    CRDTP_DESERIALIZE_FIELD("dragOperationsMask", m_dragOperationsMask),
    CRDTP_DESERIALIZE_FIELD_OPT("files", m_files),
    CRDTP_DESERIALIZE_FIELD("items", m_items),
CRDTP_END_DESERIALIZER()

CRDTP_BEGIN_SERIALIZER(DragData)
    CRDTP_SERIALIZE_FIELD("items", m_items);
    CRDTP_SERIALIZE_FIELD("files", m_files);
    CRDTP_SERIALIZE_FIELD("dragOperationsMask", m_dragOperationsMask);
CRDTP_END_SERIALIZER();


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


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

void Frontend::DragIntercepted(std::unique_ptr<protocol::Input::DragData> data)
{
    if (!frontend_channel_)
        return;
    crdtp::ObjectSerializer serializer;
    serializer.AddField(crdtp::MakeSpan("data"), data);
    frontend_channel_->SendProtocolNotification(crdtp::CreateNotification("Input.dragIntercepted", 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 dispatchDragEvent(crdtp::Dispatchable& dispatchable);
    void dispatchKeyEvent(crdtp::Dispatchable& dispatchable);
    void insertText(crdtp::Dispatchable& dispatchable);
    void imeSetComposition(crdtp::Dispatchable& dispatchable);
    void dispatchMouseEvent(crdtp::Dispatchable& dispatchable);
    void dispatchTouchEvent(crdtp::Dispatchable& dispatchable);
    void cancelDragging(crdtp::Dispatchable& dispatchable);
    void emulateTouchFromMouseEvent(crdtp::Dispatchable& dispatchable);
    void setIgnoreInputEvents(crdtp::Dispatchable& dispatchable);
    void setInterceptDrags(crdtp::Dispatchable& dispatchable);
    void synthesizePinchGesture(crdtp::Dispatchable& dispatchable);
    void synthesizeScrollGesture(crdtp::Dispatchable& dispatchable);
    void synthesizeTapGesture(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("cancelDragging"),
          &DomainDispatcherImpl::cancelDragging
    },
    {
          crdtp::SpanFrom("dispatchDragEvent"),
          &DomainDispatcherImpl::dispatchDragEvent
    },
    {
          crdtp::SpanFrom("dispatchKeyEvent"),
          &DomainDispatcherImpl::dispatchKeyEvent
    },
    {
          crdtp::SpanFrom("dispatchMouseEvent"),
          &DomainDispatcherImpl::dispatchMouseEvent
    },
    {
          crdtp::SpanFrom("dispatchTouchEvent"),
          &DomainDispatcherImpl::dispatchTouchEvent
    },
    {
          crdtp::SpanFrom("emulateTouchFromMouseEvent"),
          &DomainDispatcherImpl::emulateTouchFromMouseEvent
    },
    {
          crdtp::SpanFrom("imeSetComposition"),
          &DomainDispatcherImpl::imeSetComposition
    },
    {
          crdtp::SpanFrom("insertText"),
          &DomainDispatcherImpl::insertText
    },
    {
          crdtp::SpanFrom("setIgnoreInputEvents"),
          &DomainDispatcherImpl::setIgnoreInputEvents
    },
    {
          crdtp::SpanFrom("setInterceptDrags"),
          &DomainDispatcherImpl::setInterceptDrags
    },
    {
          crdtp::SpanFrom("synthesizePinchGesture"),
          &DomainDispatcherImpl::synthesizePinchGesture
    },
    {
          crdtp::SpanFrom("synthesizeScrollGesture"),
          &DomainDispatcherImpl::synthesizeScrollGesture
    },
    {
          crdtp::SpanFrom("synthesizeTapGesture"),
          &DomainDispatcherImpl::synthesizeTapGesture
    },
    };
    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 DispatchDragEventCallbackImpl : public Backend::DispatchDragEventCallback, public DomainDispatcher::Callback {
public:
    DispatchDragEventCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Input.dispatchDragEvent")) { }

    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 dispatchDragEventParams : public crdtp::DeserializableProtocolObject<dispatchDragEventParams> {
    String type;
    double x;
    double y;
    std::unique_ptr<protocol::Input::DragData> data;
    std::optional<int> modifiers;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(dispatchDragEventParams)
    CRDTP_DESERIALIZE_FIELD("data", data),
    CRDTP_DESERIALIZE_FIELD_OPT("modifiers", modifiers),
    CRDTP_DESERIALIZE_FIELD("type", type),
    CRDTP_DESERIALIZE_FIELD("x", x),
    CRDTP_DESERIALIZE_FIELD("y", y),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->DispatchDragEvent(params.type, params.x, params.y, std::move(params.data), std::move(params.modifiers), std::make_unique<DispatchDragEventCallbackImpl>(weakPtr(), dispatchable));
}

class DispatchKeyEventCallbackImpl : public Backend::DispatchKeyEventCallback, public DomainDispatcher::Callback {
public:
    DispatchKeyEventCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Input.dispatchKeyEvent")) { }

    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 dispatchKeyEventParams : public crdtp::DeserializableProtocolObject<dispatchKeyEventParams> {
    String type;
    std::optional<int> modifiers;
    std::optional<double> timestamp;
    std::optional<String> text;
    std::optional<String> unmodifiedText;
    std::optional<String> keyIdentifier;
    std::optional<String> code;
    std::optional<String> key;
    std::optional<int> windowsVirtualKeyCode;
    std::optional<int> nativeVirtualKeyCode;
    std::optional<bool> autoRepeat;
    std::optional<bool> isKeypad;
    std::optional<bool> isSystemKey;
    std::optional<int> location;
    std::unique_ptr<protocol::Array<String>> commands;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(dispatchKeyEventParams)
    CRDTP_DESERIALIZE_FIELD_OPT("autoRepeat", autoRepeat),
    CRDTP_DESERIALIZE_FIELD_OPT("code", code),
    CRDTP_DESERIALIZE_FIELD_OPT("commands", commands),
    CRDTP_DESERIALIZE_FIELD_OPT("isKeypad", isKeypad),
    CRDTP_DESERIALIZE_FIELD_OPT("isSystemKey", isSystemKey),
    CRDTP_DESERIALIZE_FIELD_OPT("key", key),
    CRDTP_DESERIALIZE_FIELD_OPT("keyIdentifier", keyIdentifier),
    CRDTP_DESERIALIZE_FIELD_OPT("location", location),
    CRDTP_DESERIALIZE_FIELD_OPT("modifiers", modifiers),
    CRDTP_DESERIALIZE_FIELD_OPT("nativeVirtualKeyCode", nativeVirtualKeyCode),
    CRDTP_DESERIALIZE_FIELD_OPT("text", text),
    CRDTP_DESERIALIZE_FIELD_OPT("timestamp", timestamp),
    CRDTP_DESERIALIZE_FIELD("type", type),
    CRDTP_DESERIALIZE_FIELD_OPT("unmodifiedText", unmodifiedText),
    CRDTP_DESERIALIZE_FIELD_OPT("windowsVirtualKeyCode", windowsVirtualKeyCode),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->DispatchKeyEvent(params.type, std::move(params.modifiers), std::move(params.timestamp), std::move(params.text), std::move(params.unmodifiedText), std::move(params.keyIdentifier), std::move(params.code), std::move(params.key), std::move(params.windowsVirtualKeyCode), std::move(params.nativeVirtualKeyCode), std::move(params.autoRepeat), std::move(params.isKeypad), std::move(params.isSystemKey), std::move(params.location), std::move(params.commands), std::make_unique<DispatchKeyEventCallbackImpl>(weakPtr(), dispatchable));
}

class InsertTextCallbackImpl : public Backend::InsertTextCallback, public DomainDispatcher::Callback {
public:
    InsertTextCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Input.insertText")) { }

    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 insertTextParams : public crdtp::DeserializableProtocolObject<insertTextParams> {
    String text;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(insertTextParams)
    CRDTP_DESERIALIZE_FIELD("text", text),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->InsertText(params.text, std::make_unique<InsertTextCallbackImpl>(weakPtr(), dispatchable));
}

class ImeSetCompositionCallbackImpl : public Backend::ImeSetCompositionCallback, public DomainDispatcher::Callback {
public:
    ImeSetCompositionCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Input.imeSetComposition")) { }

    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 imeSetCompositionParams : public crdtp::DeserializableProtocolObject<imeSetCompositionParams> {
    String text;
    int selectionStart;
    int selectionEnd;
    std::optional<int> replacementStart;
    std::optional<int> replacementEnd;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(imeSetCompositionParams)
    CRDTP_DESERIALIZE_FIELD_OPT("replacementEnd", replacementEnd),
    CRDTP_DESERIALIZE_FIELD_OPT("replacementStart", replacementStart),
    CRDTP_DESERIALIZE_FIELD("selectionEnd", selectionEnd),
    CRDTP_DESERIALIZE_FIELD("selectionStart", selectionStart),
    CRDTP_DESERIALIZE_FIELD("text", text),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->ImeSetComposition(params.text, params.selectionStart, params.selectionEnd, std::move(params.replacementStart), std::move(params.replacementEnd), std::make_unique<ImeSetCompositionCallbackImpl>(weakPtr(), dispatchable));
}

class DispatchMouseEventCallbackImpl : public Backend::DispatchMouseEventCallback, public DomainDispatcher::Callback {
public:
    DispatchMouseEventCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Input.dispatchMouseEvent")) { }

    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 dispatchMouseEventParams : public crdtp::DeserializableProtocolObject<dispatchMouseEventParams> {
    String type;
    double x;
    double y;
    std::optional<int> modifiers;
    std::optional<double> timestamp;
    std::optional<String> button;
    std::optional<int> buttons;
    std::optional<int> clickCount;
    std::optional<double> force;
    std::optional<double> tangentialPressure;
    std::optional<double> tiltX;
    std::optional<double> tiltY;
    std::optional<int> twist;
    std::optional<double> deltaX;
    std::optional<double> deltaY;
    std::optional<String> pointerType;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(dispatchMouseEventParams)
    CRDTP_DESERIALIZE_FIELD_OPT("button", button),
    CRDTP_DESERIALIZE_FIELD_OPT("buttons", buttons),
    CRDTP_DESERIALIZE_FIELD_OPT("clickCount", clickCount),
    CRDTP_DESERIALIZE_FIELD_OPT("deltaX", deltaX),
    CRDTP_DESERIALIZE_FIELD_OPT("deltaY", deltaY),
    CRDTP_DESERIALIZE_FIELD_OPT("force", force),
    CRDTP_DESERIALIZE_FIELD_OPT("modifiers", modifiers),
    CRDTP_DESERIALIZE_FIELD_OPT("pointerType", pointerType),
    CRDTP_DESERIALIZE_FIELD_OPT("tangentialPressure", tangentialPressure),
    CRDTP_DESERIALIZE_FIELD_OPT("tiltX", tiltX),
    CRDTP_DESERIALIZE_FIELD_OPT("tiltY", tiltY),
    CRDTP_DESERIALIZE_FIELD_OPT("timestamp", timestamp),
    CRDTP_DESERIALIZE_FIELD_OPT("twist", twist),
    CRDTP_DESERIALIZE_FIELD("type", type),
    CRDTP_DESERIALIZE_FIELD("x", x),
    CRDTP_DESERIALIZE_FIELD("y", y),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->DispatchMouseEvent(params.type, params.x, params.y, std::move(params.modifiers), std::move(params.timestamp), std::move(params.button), std::move(params.buttons), std::move(params.clickCount), std::move(params.force), std::move(params.tangentialPressure), std::move(params.tiltX), std::move(params.tiltY), std::move(params.twist), std::move(params.deltaX), std::move(params.deltaY), std::move(params.pointerType), std::make_unique<DispatchMouseEventCallbackImpl>(weakPtr(), dispatchable));
}

class DispatchTouchEventCallbackImpl : public Backend::DispatchTouchEventCallback, public DomainDispatcher::Callback {
public:
    DispatchTouchEventCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Input.dispatchTouchEvent")) { }

    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 dispatchTouchEventParams : public crdtp::DeserializableProtocolObject<dispatchTouchEventParams> {
    String type;
    std::unique_ptr<protocol::Array<protocol::Input::TouchPoint>> touchPoints;
    std::optional<int> modifiers;
    std::optional<double> timestamp;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(dispatchTouchEventParams)
    CRDTP_DESERIALIZE_FIELD_OPT("modifiers", modifiers),
    CRDTP_DESERIALIZE_FIELD_OPT("timestamp", timestamp),
    CRDTP_DESERIALIZE_FIELD("touchPoints", touchPoints),
    CRDTP_DESERIALIZE_FIELD("type", type),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->DispatchTouchEvent(params.type, std::move(params.touchPoints), std::move(params.modifiers), std::move(params.timestamp), std::make_unique<DispatchTouchEventCallbackImpl>(weakPtr(), dispatchable));
}

class CancelDraggingCallbackImpl : public Backend::CancelDraggingCallback, public DomainDispatcher::Callback {
public:
    CancelDraggingCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Input.cancelDragging")) { }

    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 {


}  // namespace

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

    m_backend->CancelDragging(std::make_unique<CancelDraggingCallbackImpl>(weakPtr(), dispatchable));
}

namespace {

struct emulateTouchFromMouseEventParams : public crdtp::DeserializableProtocolObject<emulateTouchFromMouseEventParams> {
    String type;
    int x;
    int y;
    String button;
    std::optional<double> timestamp;
    std::optional<double> deltaX;
    std::optional<double> deltaY;
    std::optional<int> modifiers;
    std::optional<int> clickCount;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(emulateTouchFromMouseEventParams)
    CRDTP_DESERIALIZE_FIELD("button", button),
    CRDTP_DESERIALIZE_FIELD_OPT("clickCount", clickCount),
    CRDTP_DESERIALIZE_FIELD_OPT("deltaX", deltaX),
    CRDTP_DESERIALIZE_FIELD_OPT("deltaY", deltaY),
    CRDTP_DESERIALIZE_FIELD_OPT("modifiers", modifiers),
    CRDTP_DESERIALIZE_FIELD_OPT("timestamp", timestamp),
    CRDTP_DESERIALIZE_FIELD("type", type),
    CRDTP_DESERIALIZE_FIELD("x", x),
    CRDTP_DESERIALIZE_FIELD("y", y),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    std::unique_ptr<DomainDispatcher::WeakPtr> weak = weakPtr();
    DispatchResponse response = m_backend->EmulateTouchFromMouseEvent(params.type, params.x, params.y, params.button, std::move(params.timestamp), std::move(params.deltaX), std::move(params.deltaY), std::move(params.modifiers), std::move(params.clickCount));
    if (response.IsFallThrough()) {
        dispatchable.DispatchFallThrough(response.Message());
        return;
    }
    if (weak->get())
        weak->get()->sendResponse(dispatchable.CallId(), response);
    return;
}

namespace {

struct setIgnoreInputEventsParams : public crdtp::DeserializableProtocolObject<setIgnoreInputEventsParams> {
    bool ignore;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(setIgnoreInputEventsParams)
    CRDTP_DESERIALIZE_FIELD("ignore", ignore),
CRDTP_END_DESERIALIZER()

}  // namespace

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

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

namespace {

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

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

}  // namespace

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

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

class SynthesizePinchGestureCallbackImpl : public Backend::SynthesizePinchGestureCallback, public DomainDispatcher::Callback {
public:
    SynthesizePinchGestureCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Input.synthesizePinchGesture")) { }

    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 synthesizePinchGestureParams : public crdtp::DeserializableProtocolObject<synthesizePinchGestureParams> {
    double x;
    double y;
    double scaleFactor;
    std::optional<int> relativeSpeed;
    std::optional<String> gestureSourceType;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(synthesizePinchGestureParams)
    CRDTP_DESERIALIZE_FIELD_OPT("gestureSourceType", gestureSourceType),
    CRDTP_DESERIALIZE_FIELD_OPT("relativeSpeed", relativeSpeed),
    CRDTP_DESERIALIZE_FIELD("scaleFactor", scaleFactor),
    CRDTP_DESERIALIZE_FIELD("x", x),
    CRDTP_DESERIALIZE_FIELD("y", y),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->SynthesizePinchGesture(params.x, params.y, params.scaleFactor, std::move(params.relativeSpeed), std::move(params.gestureSourceType), std::make_unique<SynthesizePinchGestureCallbackImpl>(weakPtr(), dispatchable));
}

class SynthesizeScrollGestureCallbackImpl : public Backend::SynthesizeScrollGestureCallback, public DomainDispatcher::Callback {
public:
    SynthesizeScrollGestureCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Input.synthesizeScrollGesture")) { }

    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 synthesizeScrollGestureParams : public crdtp::DeserializableProtocolObject<synthesizeScrollGestureParams> {
    double x;
    double y;
    std::optional<double> xDistance;
    std::optional<double> yDistance;
    std::optional<double> xOverscroll;
    std::optional<double> yOverscroll;
    std::optional<bool> preventFling;
    std::optional<int> speed;
    std::optional<String> gestureSourceType;
    std::optional<int> repeatCount;
    std::optional<int> repeatDelayMs;
    std::optional<String> interactionMarkerName;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(synthesizeScrollGestureParams)
    CRDTP_DESERIALIZE_FIELD_OPT("gestureSourceType", gestureSourceType),
    CRDTP_DESERIALIZE_FIELD_OPT("interactionMarkerName", interactionMarkerName),
    CRDTP_DESERIALIZE_FIELD_OPT("preventFling", preventFling),
    CRDTP_DESERIALIZE_FIELD_OPT("repeatCount", repeatCount),
    CRDTP_DESERIALIZE_FIELD_OPT("repeatDelayMs", repeatDelayMs),
    CRDTP_DESERIALIZE_FIELD_OPT("speed", speed),
    CRDTP_DESERIALIZE_FIELD("x", x),
    CRDTP_DESERIALIZE_FIELD_OPT("xDistance", xDistance),
    CRDTP_DESERIALIZE_FIELD_OPT("xOverscroll", xOverscroll),
    CRDTP_DESERIALIZE_FIELD("y", y),
    CRDTP_DESERIALIZE_FIELD_OPT("yDistance", yDistance),
    CRDTP_DESERIALIZE_FIELD_OPT("yOverscroll", yOverscroll),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->SynthesizeScrollGesture(params.x, params.y, std::move(params.xDistance), std::move(params.yDistance), std::move(params.xOverscroll), std::move(params.yOverscroll), std::move(params.preventFling), std::move(params.speed), std::move(params.gestureSourceType), std::move(params.repeatCount), std::move(params.repeatDelayMs), std::move(params.interactionMarkerName), std::make_unique<SynthesizeScrollGestureCallbackImpl>(weakPtr(), dispatchable));
}

class SynthesizeTapGestureCallbackImpl : public Backend::SynthesizeTapGestureCallback, public DomainDispatcher::Callback {
public:
    SynthesizeTapGestureCallbackImpl(std::unique_ptr<DomainDispatcher::WeakPtr> backendImpl, crdtp::Dispatchable& dispatchable)
        : DomainDispatcher::Callback(std::move(backendImpl), dispatchable, crdtp::SpanFrom("Input.synthesizeTapGesture")) { }

    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 synthesizeTapGestureParams : public crdtp::DeserializableProtocolObject<synthesizeTapGestureParams> {
    double x;
    double y;
    std::optional<int> duration;
    std::optional<int> tapCount;
    std::optional<String> gestureSourceType;
    DECLARE_DESERIALIZATION_SUPPORT();
};

CRDTP_BEGIN_DESERIALIZER(synthesizeTapGestureParams)
    CRDTP_DESERIALIZE_FIELD_OPT("duration", duration),
    CRDTP_DESERIALIZE_FIELD_OPT("gestureSourceType", gestureSourceType),
    CRDTP_DESERIALIZE_FIELD_OPT("tapCount", tapCount),
    CRDTP_DESERIALIZE_FIELD("x", x),
    CRDTP_DESERIALIZE_FIELD("y", y),
CRDTP_END_DESERIALIZER()

}  // namespace

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

    m_backend->SynthesizeTapGesture(params.x, params.y, std::move(params.duration), std::move(params.tapCount), std::move(params.gestureSourceType), std::make_unique<SynthesizeTapGestureCallbackImpl>(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("Input"), SortedRedirects(), std::move(dispatcher));
}

} // Input
} // namespace content
} // namespace protocol
