// This file is generated by DispatcherBase_h.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.

#ifndef {{"_".join(config.protocol.namespace)}}_DispatcherBase_h
#define {{"_".join(config.protocol.namespace)}}_DispatcherBase_h

//#include "Forward.h"
//#include "ErrorSupport.h"
//#include "Values.h"

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

class WeakPtr;

class {{config.lib.export_macro}} DispatchResponse {
public:
    enum Status {
        kSuccess = 0,
        kError = 1,
        kFallThrough = 2,
    };

    // For historical reasons, these error codes correspond to commonly used
    // XMLRPC codes (e.g. see METHOD_NOT_FOUND in
    // https://github.com/python/cpython/blob/master/Lib/xmlrpc/client.py).
    enum ErrorCode {
        kParseError = -32700,
        kInvalidRequest = -32600,
        kMethodNotFound = -32601,
        kInvalidParams = -32602,
        kInternalError = -32603,
        kServerError = -32000,
    };

    Status status() const { return m_status; }
    const String& errorMessage() const { return m_errorMessage; }
    ErrorCode errorCode() const { return m_errorCode; }
    bool isSuccess() const { return m_status == kSuccess; }

    static DispatchResponse OK();
    static DispatchResponse Error(const String&);
    static DispatchResponse InternalError();
    static DispatchResponse InvalidParams(const String&);
    static DispatchResponse FallThrough();

private:
    Status m_status;
    String m_errorMessage;
    ErrorCode m_errorCode;
};

class {{config.lib.export_macro}} DispatcherBase {
    PROTOCOL_DISALLOW_COPY(DispatcherBase);
public:
    static const char kInvalidParamsString[];
    class {{config.lib.export_macro}} WeakPtr {
    public:
        explicit WeakPtr(DispatcherBase*);
        ~WeakPtr();
        DispatcherBase* get() { return m_dispatcher; }
        void dispose() { m_dispatcher = nullptr; }

    private:
        DispatcherBase* m_dispatcher;
    };

    class {{config.lib.export_macro}} Callback {
    public:
        Callback(std::unique_ptr<WeakPtr> backendImpl, int callId, const String& method, const ProtocolMessage& message);
        virtual ~Callback();
        void dispose();

    protected:
        void sendIfActive(std::unique_ptr<protocol::DictionaryValue> partialMessage, const DispatchResponse& response);
        void fallThroughIfActive();

    private:
        std::unique_ptr<WeakPtr> m_backendImpl;
        int m_callId;
        String m_method;
        ProtocolMessage m_message;
    };

    explicit DispatcherBase(FrontendChannel*);
    virtual ~DispatcherBase();

    virtual bool canDispatch(const String& method) = 0;
    virtual void dispatch(int callId, const String& method, const ProtocolMessage& rawMessage, std::unique_ptr<protocol::DictionaryValue> messageObject) = 0;
    FrontendChannel* channel() { return m_frontendChannel; }

    void sendResponse(int callId, const DispatchResponse&, std::unique_ptr<protocol::DictionaryValue> result);
    void sendResponse(int callId, const DispatchResponse&);

    void reportProtocolError(int callId, DispatchResponse::ErrorCode, const String& errorMessage, ErrorSupport* errors);
    void clearFrontend();

    std::unique_ptr<WeakPtr> weakPtr();

private:
    FrontendChannel* m_frontendChannel;
    std::unordered_set<WeakPtr*> m_weakPtrs;
};

class {{config.lib.export_macro}} UberDispatcher {
    PROTOCOL_DISALLOW_COPY(UberDispatcher);
public:
    explicit UberDispatcher(FrontendChannel*);
    void registerBackend(const String& name, std::unique_ptr<protocol::DispatcherBase>);
    void setupRedirects(const std::unordered_map<String, String>&);
    bool parseCommand(Value* message, int* callId, String* method);
    bool canDispatch(const String& method);
    void dispatch(int callId, const String& method, std::unique_ptr<Value> message, const ProtocolMessage& rawMessage);
    FrontendChannel* channel() { return m_frontendChannel; }
    virtual ~UberDispatcher();

private:
    protocol::DispatcherBase* findDispatcher(const String& method);
    FrontendChannel* m_frontendChannel;
    std::unordered_map<String, String> m_redirects;
    std::unordered_map<String, std::unique_ptr<protocol::DispatcherBase>> m_dispatchers;
};

class InternalResponse : public Serializable {
    PROTOCOL_DISALLOW_COPY(InternalResponse);
public:
    static std::unique_ptr<Serializable> createResponse(int callId, std::unique_ptr<Serializable> params);
    static std::unique_ptr<Serializable> createNotification(const char* method, std::unique_ptr<Serializable> params = nullptr);
    static std::unique_ptr<Serializable> createErrorResponse(int callId, DispatchResponse::ErrorCode code, const String& message);

    void AppendSerialized(std::vector<uint8_t>* out) const override;

    ~InternalResponse() override {}

private:
    InternalResponse(int callId, const char* method, std::unique_ptr<Serializable> params);

    int m_callId;
    const char* m_method = nullptr;
    std::unique_ptr<Serializable> m_params;
};

class InternalRawNotification : public Serializable {
public:
    static std::unique_ptr<InternalRawNotification> fromBinary(std::vector<uint8_t> notification)
    {
        return std::unique_ptr<InternalRawNotification>(new InternalRawNotification(std::move(notification)));
    }

    ~InternalRawNotification() override {}

    std::vector<uint8_t> TakeSerialized() && override {
        return std::move(m_binaryNotification);
    }

    void AppendSerialized(std::vector<uint8_t>* out) const override
    {
        out->insert(out->end(), m_binaryNotification.begin(), m_binaryNotification.end());
    }

private:
  explicit InternalRawNotification(std::vector<uint8_t> notification)
    : m_binaryNotification(std::move(notification)) { }

  std::vector<uint8_t> m_binaryNotification;
};

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

#endif // !defined({{"_".join(config.protocol.namespace)}}_DispatcherBase_h)
