#ifndef _BLOCKING_CHANNEL_H_
#define _BLOCKING_CHANNEL_H_

#include "util/AggreReadableByteChannel.h"
#include "util/AggreWritableByteChannel.h"

#include "util/simpleobject/AgString.h"

#include <boost/asio.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/asio/deadline_timer.hpp>

#include <boost/bind.hpp>

#include <boost/lockfree/queue.hpp>

#ifdef __GNUC__
    #include <stdio.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
#endif

class BlockingChannel : public AggreReadableByteChannel, public AggreWritableByteChannel
{
public:
    BlockingChannel(int64_t timeout); // SSL
    BlockingChannel(bool isSsl = false); // SSL optionally

#ifdef __GNUC__
    BlockingChannel(int socket); // No SSL
#else
    BlockingChannel(SOCKET socket); // No SSL
#endif

    virtual ~BlockingChannel();

    virtual void connect(const AgString &ip, unsigned short port);
    virtual void disconnect();

    virtual int read(boost::asio::streambuf &dst);
    virtual int write(std::vector<unsigned char>& src);

    virtual void close();
    virtual bool isOpen();

private:

    boost::asio::ip::tcp::endpoint mEndPoint;
    boost::asio::io_service mIos;
    boost::asio::ssl::stream<boost::asio::ip::tcp::socket> *mSslSocket;
    boost::asio::ssl::context mCtx;
    boost::asio::streambuf mBuffer;

    bool mIsConnected;
    bool mIsClosing;
    int64_t mTimeout;

    bool verify_certificate(bool preverified, boost::asio::ssl::verify_context& ctx);
    virtual void connect(boost::asio::ip::tcp::resolver::iterator &endpoint);

    bool mReadySocket;

#ifdef __GNUC__
    int socket_;
    struct sockaddr_in server_;
#else
    SOCKET socket_;
    struct addrinfo *result,
                    *ptr,
                    hints;
#endif

    bool mSsl;
};

#endif
