// This file is generated by DispatcherBase_cpp.template.

// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//#include "DispatcherBase.h"
//#include "Parser.h"

{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}

// static
DispatchResponse DispatchResponse::OK()
{
    DispatchResponse result;
    result.m_status = kSuccess;
    result.m_errorCode = kParseError;
    return result;
}

// static
DispatchResponse DispatchResponse::Error(const String& error)
{
    DispatchResponse result;
    result.m_status = kError;
    result.m_errorCode = kServerError;
    result.m_errorMessage = error;
    return result;
}

// static
DispatchResponse DispatchResponse::InternalError()
{
    DispatchResponse result;
    result.m_status = kError;
    result.m_errorCode = kInternalError;
    result.m_errorMessage = "Internal error";
    return result;
}

// static
DispatchResponse DispatchResponse::InvalidParams(const String& error)
{
    DispatchResponse result;
    result.m_status = kError;
    result.m_errorCode = kInvalidParams;
    result.m_errorMessage = error;
    return result;
}

// static
DispatchResponse DispatchResponse::FallThrough()
{
    DispatchResponse result;
    result.m_status = kFallThrough;
    result.m_errorCode = kParseError;
    return result;
}

// static
const char DispatcherBase::kInvalidParamsString[] = "Invalid parameters";

DispatcherBase::WeakPtr::WeakPtr(DispatcherBase* dispatcher) : m_dispatcher(dispatcher) { }

DispatcherBase::WeakPtr::~WeakPtr()
{
    if (m_dispatcher)
        m_dispatcher->m_weakPtrs.erase(this);
}

DispatcherBase::Callback::Callback(std::unique_ptr<DispatcherBase::WeakPtr> backendImpl, int callId, const String& method, const String& message)
    : m_backendImpl(std::move(backendImpl))
    , m_callId(callId)
    , m_method(method)
    , m_message(message) { }

DispatcherBase::Callback::~Callback() = default;

void DispatcherBase::Callback::dispose()
{
    m_backendImpl = nullptr;
}

void DispatcherBase::Callback::sendIfActive(std::unique_ptr<protocol::DictionaryValue> partialMessage, const DispatchResponse& response)
{
    if (!m_backendImpl || !m_backendImpl->get())
        return;
    m_backendImpl->get()->sendResponse(m_callId, response, std::move(partialMessage));
    m_backendImpl = nullptr;
}

void DispatcherBase::Callback::fallThroughIfActive()
{
    if (!m_backendImpl || !m_backendImpl->get())
        return;
    m_backendImpl->get()->channel()->fallThrough(m_callId, m_method, m_message);
    m_backendImpl = nullptr;
}

DispatcherBase::DispatcherBase(FrontendChannel* frontendChannel)
    : m_frontendChannel(frontendChannel) { }

DispatcherBase::~DispatcherBase()
{
    clearFrontend();
}

void DispatcherBase::sendResponse(int callId, const DispatchResponse& response, std::unique_ptr<protocol::DictionaryValue> result)
{
    if (!m_frontendChannel)
        return;
    if (response.status() == DispatchResponse::kError) {
        reportProtocolError(callId, response.errorCode(), response.errorMessage(), nullptr);
        return;
    }
    m_frontendChannel->sendProtocolResponse(callId, InternalResponse::createResponse(callId, std::move(result)));
}

void DispatcherBase::sendResponse(int callId, const DispatchResponse& response)
{
    sendResponse(callId, response, DictionaryValue::create());
}

namespace {

class ProtocolError : public Serializable {
public:
    static std::unique_ptr<ProtocolError> createErrorResponse(int callId, DispatchResponse::ErrorCode code, const String& errorMessage, ErrorSupport* errors)
    {
        std::unique_ptr<ProtocolError> protocolError(new ProtocolError(code, errorMessage));
        protocolError->m_callId = callId;
        protocolError->m_hasCallId = true;
        if (errors && errors->hasErrors())
            protocolError->m_data = errors->errors();
        return protocolError;
    }

    static std::unique_ptr<ProtocolError> createErrorNotification(DispatchResponse::ErrorCode code, const String& errorMessage)
    {
        return std::unique_ptr<ProtocolError>(new ProtocolError(code, errorMessage));
    }

    String serialize() override
    {
        std::unique_ptr<protocol::DictionaryValue> error = DictionaryValue::create();
        error->setInteger("code", m_code);
        error->setString("message", m_errorMessage);
        if (m_data.length())
            error->setString("data", m_data);
        std::unique_ptr<protocol::DictionaryValue> message = DictionaryValue::create();
        message->setObject("error", std::move(error));
        if (m_hasCallId)
            message->setInteger("id", m_callId);
        return message->serialize();
    }

    ~ProtocolError() override {}

private:
    ProtocolError(DispatchResponse::ErrorCode code, const String& errorMessage)
        : m_code(code)
        , m_errorMessage(errorMessage)
    {
    }

    DispatchResponse::ErrorCode m_code;
    String m_errorMessage;
    String m_data;
    int m_callId = 0;
    bool m_hasCallId = false;
};

} // namespace

static void reportProtocolErrorTo(FrontendChannel* frontendChannel, int callId, DispatchResponse::ErrorCode code, const String& errorMessage, ErrorSupport* errors)
{
    if (frontendChannel)
        frontendChannel->sendProtocolResponse(callId, ProtocolError::createErrorResponse(callId, code, errorMessage, errors));
}

static void reportProtocolErrorTo(FrontendChannel* frontendChannel, DispatchResponse::ErrorCode code, const String& errorMessage)
{
    if (frontendChannel)
        frontendChannel->sendProtocolNotification(ProtocolError::createErrorNotification(code, errorMessage));
}

void DispatcherBase::reportProtocolError(int callId, DispatchResponse::ErrorCode code, const String& errorMessage, ErrorSupport* errors)
{
    reportProtocolErrorTo(m_frontendChannel, callId, code, errorMessage, errors);
}

void DispatcherBase::clearFrontend()
{
    m_frontendChannel = nullptr;
    for (auto& weak : m_weakPtrs)
        weak->dispose();
    m_weakPtrs.clear();
}

std::unique_ptr<DispatcherBase::WeakPtr> DispatcherBase::weakPtr()
{
    std::unique_ptr<DispatcherBase::WeakPtr> weak(new DispatcherBase::WeakPtr(this));
    m_weakPtrs.insert(weak.get());
    return weak;
}

UberDispatcher::UberDispatcher(FrontendChannel* frontendChannel)
    : m_frontendChannel(frontendChannel) { }

void UberDispatcher::registerBackend(const String& name, std::unique_ptr<protocol::DispatcherBase> dispatcher)
{
    m_dispatchers[name] = std::move(dispatcher);
}

void UberDispatcher::setupRedirects(const std::unordered_map<String, String>& redirects)
{
    for (const auto& pair : redirects)
        m_redirects[pair.first] = pair.second;
}

bool UberDispatcher::parseCommand(Value* parsedMessage, int* outCallId, String* outMethod) {
    if (!parsedMessage) {
        reportProtocolErrorTo(m_frontendChannel, DispatchResponse::kParseError, "Message must be a valid JSON");
        return false;
    }
    protocol::DictionaryValue* messageObject = DictionaryValue::cast(parsedMessage);
    if (!messageObject) {
        reportProtocolErrorTo(m_frontendChannel, DispatchResponse::kInvalidRequest, "Message must be an object");
        return false;
    }

    int callId = 0;
    protocol::Value* callIdValue = messageObject->get("id");
    bool success = callIdValue && callIdValue->asInteger(&callId);
    if (!success) {
        reportProtocolErrorTo(m_frontendChannel, DispatchResponse::kInvalidRequest, "Message must have integer 'id' property");
        return false;
    }
    if (outCallId)
      *outCallId = callId;

    protocol::Value* methodValue = messageObject->get("method");
    String method;
    success = methodValue && methodValue->asString(&method);
    if (!success) {
        reportProtocolErrorTo(m_frontendChannel, callId, DispatchResponse::kInvalidRequest, "Message must have string 'method' property", nullptr);
        return false;
    }
    if (outMethod)
      *outMethod = method;
    return true;
}

protocol::DispatcherBase* UberDispatcher::findDispatcher(const String& method) {
    size_t dotIndex = StringUtil::find(method, ".");
    if (dotIndex == StringUtil::kNotFound)
        return nullptr;
    String domain = StringUtil::substring(method, 0, dotIndex);
    auto it = m_dispatchers.find(domain);
    if (it == m_dispatchers.end())
        return nullptr;
    if (!it->second->canDispatch(method))
        return nullptr;
    return it->second.get();
}

bool UberDispatcher::canDispatch(const String& in_method)
{
    String method = in_method;
    auto redirectIt = m_redirects.find(method);
    if (redirectIt != m_redirects.end())
        method = redirectIt->second;
    return !!findDispatcher(method);
}

void UberDispatcher::dispatch(int callId, const String& in_method, std::unique_ptr<Value> parsedMessage, const String& rawMessage)
{
    String method = in_method;
    auto redirectIt = m_redirects.find(method);
    if (redirectIt != m_redirects.end())
        method = redirectIt->second;
    protocol::DispatcherBase* dispatcher = findDispatcher(method);
    if (!dispatcher) {
        reportProtocolErrorTo(m_frontendChannel, callId, DispatchResponse::kMethodNotFound, "'" + method + "' wasn't found", nullptr);
        return;
    }
    std::unique_ptr<protocol::DictionaryValue> messageObject = DictionaryValue::cast(std::move(parsedMessage));
    dispatcher->dispatch(callId, method, rawMessage, std::move(messageObject));
}

UberDispatcher::~UberDispatcher() = default;

// static
std::unique_ptr<InternalResponse> InternalResponse::createResponse(int callId, std::unique_ptr<Serializable> params)
{
    return std::unique_ptr<InternalResponse>(new InternalResponse(callId, String(), std::move(params)));
}

// static
std::unique_ptr<InternalResponse> InternalResponse::createNotification(const String& notification, std::unique_ptr<Serializable> params)
{
    return std::unique_ptr<InternalResponse>(new InternalResponse(0, notification, std::move(params)));
}

String InternalResponse::serialize()
{
    std::unique_ptr<DictionaryValue> result = DictionaryValue::create();
    std::unique_ptr<Serializable> params(m_params ? std::move(m_params) : DictionaryValue::create());
    if (m_notification.length()) {
        result->setString("method", m_notification);
        result->setValue("params", SerializedValue::create(params->serialize()));
    } else {
        result->setInteger("id", m_callId);
        result->setValue("result", SerializedValue::create(params->serialize()));
    }
    return result->serialize();
}

InternalResponse::InternalResponse(int callId, const String& notification, std::unique_ptr<Serializable> params)
    : m_callId(callId)
    , m_notification(notification)
    , m_params(params ? std::move(params) : nullptr)
{
}

{% for namespace in config.protocol.namespace %}
} // namespace {{namespace}}
{% endfor %}
