#ifndef EASYWSCLIENT_HPP_20120819_MIOFVASDTNUASZDQPLFD
#define EASYWSCLIENT_HPP_20120819_MIOFVASDTNUASZDQPLFD

// This code comes from:
// https://github.com/dhbaird/easywsclient
//
// To get the latest version:
// wget https://raw.github.com/dhbaird/easywsclient/master/easywsclient.hpp
// wget https://raw.github.com/dhbaird/easywsclient/master/easywsclient.cpp

#include <string>
#include <vector>

namespace easywsclient
{

    struct Callback_Imp
    {
        virtual void operator()(const std::string &message) = 0;
    };
    struct BytesCallback_Imp
    {
        virtual void operator()(const std::vector<uint8_t> &message) = 0;
    };

    class WebSocket
    {
    public:
        typedef WebSocket *pointer;
        typedef enum readyStateValues
        {
            CLOSING,
            CLOSED,
            CONNECTING,
            OPEN
        } readyStateValues;

        // Factories:
        static pointer create_dummy();
        static pointer from_url(const std::string &url, const std::string &origin = std::string());
        static pointer from_url(const std::string &url, const std::string &origin = std::string(), bool internal = false);
        static pointer from_url_no_mask(const std::string &url, const std::string &origin = std::string());

        // Interfaces:
        virtual ~WebSocket() {}
        virtual void poll(int timeout = 0) = 0; // timeout in milliseconds
        virtual void send(const std::string &message) = 0;
        virtual void sendBinary(const std::string &message) = 0;
        virtual void sendBinary(const std::vector<uint8_t> &message) = 0;
        virtual void sendPing() = 0;
        virtual void close() = 0;
        virtual readyStateValues getReadyState() const = 0;

        template <class Callable>
        void dispatch(Callable callable)
        // For callbacks that accept a string argument.
        { // N.B. this is compatible with both C++11 lambdas, functors and C function pointers
            struct _Callback : public Callback_Imp
            {
                Callable &callable;
                _Callback(Callable &callable) : callable(callable) {}
                void operator()(const std::string &message) { callable(message); }
            };
            _Callback callback(callable);
            _dispatch(callback);
        }

        template <class Callable>
        void dispatchBinary(Callable callable)
        // For callbacks that accept a std::vector<uint8_t> argument.
        { // N.B. this is compatible with both C++11 lambdas, functors and C function pointers
            struct _Callback : public BytesCallback_Imp
            {
                Callable &callable;
                _Callback(Callable &callable) : callable(callable) {}
                void operator()(const std::vector<uint8_t> &message) { callable(message); }
            };
            _Callback callback(callable);
            _dispatchBinary(callback);
        }

    protected:
        virtual void _dispatch(Callback_Imp &callable) = 0;
        virtual void _dispatchBinary(BytesCallback_Imp &callable) = 0;
    };

} // namespace easywsclient

#endif /* EASYWSCLIENT_HPP_20120819_MIOFVASDTNUASZDQPLFD */
